Imported Upstream version 1.57.0
[platform/upstream/boost.git] / libs / msm / test / OrthogonalDeferred2.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         typedef player_ p; // makes transition table cleaner
253
254         // Transition table for player
255         struct transition_table : mpl::vector<
256             //      Start     Event         Next      Action               Guard
257             //    +---------+-------------+---------+---------------------+----------------------+
258             a_row < Stopped , play        , Playing , &p::start_playback                         >,
259             a_row < Stopped , open_close  , Open    , &p::open_drawer                            >,
260              _row < Stopped , stop        , Stopped                                              >,
261             //  +---------+-------------+---------+---------------------+----------------------+
262             g_row < Open    , open_close  , Empty   ,                     &p::can_close_drawer   >,
263             Row   < Open    , play        , none    , Defer             , none                   >,
264             //  +---------+-------------+---------+---------------------+----------------------+
265             a_row < Empty   , open_close  , Open    , &p::open_drawer                            >,
266             a_row < Empty   , cd_detected , Stopped , &p::store_cd_info                          >,
267             Row   < Empty   , play        , none    , Defer             , none                   >,
268             //  +---------+-------------+---------+---------------------+----------------------+
269             a_row < Playing , stop        , Stopped , &p::stop_playback                          >,
270             a_row < Playing , pause       , Paused  , &p::pause_playback                         >,
271             a_row < Playing , open_close  , Open    , &p::stop_and_open                          >,
272             //  +---------+-------------+---------+---------------------+----------------------+
273             a_row < Paused  , end_pause   , Playing , &p::resume_playback                        >,
274             a_row < Paused  , stop        , Stopped , &p::stop_playback                          >,
275             a_row < Paused  , open_close  , Open    , &p::stop_and_open                          >,
276             //    +---------+-------------+---------+---------------------+----------------------+
277             a_row < AllOk   , error_found ,ErrorMode, &p::report_error                           >,
278             a_row <ErrorMode, end_error   ,AllOk    , &p::report_end_error                       >,
279              _row < AllOk   , do_terminate,ErrorTerminate                                        >
280             //    +---------+-------------+---------+---------------------+----------------------+
281         > {};
282
283         // Replaces the default no-transition response.
284         template <class FSM,class Event>
285         void no_transition(Event const& , FSM&,int)
286         {
287             BOOST_FAIL("no_transition called!");
288         }
289         // init counters
290         template <class Event,class FSM>
291         void on_entry(Event const&,FSM& fsm) 
292         {
293             fsm.template get_state<player_::Stopped&>().entry_counter=0;
294             fsm.template get_state<player_::Stopped&>().exit_counter=0;
295             fsm.template get_state<player_::Open&>().entry_counter=0;
296             fsm.template get_state<player_::Open&>().exit_counter=0;
297             fsm.template get_state<player_::Empty&>().entry_counter=0;
298             fsm.template get_state<player_::Empty&>().exit_counter=0;
299             fsm.template get_state<player_::Playing&>().entry_counter=0;
300             fsm.template get_state<player_::Playing&>().exit_counter=0;
301             fsm.template get_state<player_::Playing&>().template get_state<player_::Playing::Song1&>().entry_counter=0;
302             fsm.template get_state<player_::Playing&>().template get_state<player_::Playing::Song1&>().exit_counter=0;
303             fsm.template get_state<player_::Playing&>().template get_state<player_::Playing::Song2&>().entry_counter=0;
304             fsm.template get_state<player_::Playing&>().template get_state<player_::Playing::Song2&>().exit_counter=0;
305             fsm.template get_state<player_::Playing&>().template get_state<player_::Playing::Song3&>().entry_counter=0;
306             fsm.template get_state<player_::Playing&>().template get_state<player_::Playing::Song3&>().exit_counter=0;
307             fsm.template get_state<player_::Paused&>().entry_counter=0;
308             fsm.template get_state<player_::Paused&>().exit_counter=0;
309             fsm.template get_state<player_::AllOk&>().entry_counter=0;
310             fsm.template get_state<player_::AllOk&>().exit_counter=0;
311             fsm.template get_state<player_::ErrorMode&>().entry_counter=0;
312             fsm.template get_state<player_::ErrorMode&>().exit_counter=0;
313             fsm.template get_state<player_::ErrorTerminate&>().entry_counter=0;
314             fsm.template get_state<player_::ErrorTerminate&>().exit_counter=0;
315         }
316     };
317     // Pick a back-end
318     typedef msm::back::state_machine<player_> player;
319
320     //static char const* const state_names[] = { "Stopped", "Open", "Empty", "Playing", "Paused","AllOk","ErrorMode" };
321
322     BOOST_AUTO_TEST_CASE( my_test )
323     {
324         player p;
325         // needed to start the highest-level SM. This will call on_entry and mark the start of the SM
326         p.start(); 
327         // test deferred event
328         // deferred in Empty and Open, will be handled only after event cd_detected
329         p.process_event(play());
330         BOOST_CHECK_MESSAGE(p.current_state()[0] == 2,"Empty should be active"); //Empty
331         BOOST_CHECK_MESSAGE(p.get_state<player_::Open&>().exit_counter == 0,"Open exit not called correctly");
332         BOOST_CHECK_MESSAGE(p.get_state<player_::Playing&>().entry_counter == 0,"Playing entry not called correctly");
333         BOOST_CHECK_MESSAGE(p.get_state<player_::Empty&>().entry_counter == 1,"Empty entry not called correctly");
334         //flags
335         BOOST_CHECK_MESSAGE(p.is_flag_active<CDLoaded>() == false,"CDLoaded should not be active");
336
337         p.process_event(open_close()); 
338         BOOST_CHECK_MESSAGE(p.current_state()[0] == 1,"Open should be active"); //Open
339         BOOST_CHECK_MESSAGE(p.get_state<player_::Empty&>().exit_counter == 1,"Empty exit not called correctly");
340         BOOST_CHECK_MESSAGE(p.get_state<player_::Open&>().entry_counter == 1,"Open entry not called correctly");
341
342         p.process_event(open_close()); 
343         BOOST_CHECK_MESSAGE(p.current_state()[0] == 2,"Empty should be active"); //Empty
344         BOOST_CHECK_MESSAGE(p.get_state<player_::Open&>().exit_counter == 1,"Open exit not called correctly");
345         BOOST_CHECK_MESSAGE(p.get_state<player_::Empty&>().entry_counter == 2,"Empty entry not called correctly");
346         BOOST_CHECK_MESSAGE(p.can_close_drawer_counter == 1,"guard not called correctly");
347
348         //deferred event should have been processed
349         p.process_event(cd_detected("louie, louie")); 
350         BOOST_CHECK_MESSAGE(p.current_state()[0] == 3,"Playing should be active"); //Playing
351         BOOST_CHECK_MESSAGE(p.get_state<player_::Empty&>().exit_counter == 2,"Empty exit not called correctly");
352         BOOST_CHECK_MESSAGE(p.get_state<player_::Stopped&>().entry_counter == 1,"Stopped entry not called correctly");
353         BOOST_CHECK_MESSAGE(p.get_state<player_::Stopped&>().exit_counter == 1,"Stopped exit not called correctly");
354         BOOST_CHECK_MESSAGE(p.get_state<player_::Playing&>().entry_counter == 1,"Playing entry not called correctly");
355         BOOST_CHECK_MESSAGE(p.start_playback_counter == 1,"action not called correctly");
356         BOOST_CHECK_MESSAGE(p.get_state<player_::Playing&>().current_state()[0] == 0,"Song1 should be active");
357         BOOST_CHECK_MESSAGE(
358             p.get_state<player_::Playing&>().get_state<player_::Playing::Song1&>().entry_counter == 1,
359             "Song1 entry not called correctly");
360
361         //flags
362         BOOST_CHECK_MESSAGE(p.is_flag_active<PlayingPaused>() == true,"PlayingPaused should be active");
363         BOOST_CHECK_MESSAGE(p.is_flag_active<FirstSongPlaying>() == true,"FirstSongPlaying should be active");
364
365
366         p.process_event(NextSong());
367         BOOST_CHECK_MESSAGE(p.current_state()[0] == 3,"Playing should be active"); //Playing
368         BOOST_CHECK_MESSAGE(p.get_state<player_::Playing&>().current_state()[0] == 1,"Song2 should be active");
369         BOOST_CHECK_MESSAGE(
370             p.get_state<player_::Playing&>().get_state<player_::Playing::Song2&>().entry_counter == 1,
371             "Song2 entry not called correctly");
372         BOOST_CHECK_MESSAGE(
373             p.get_state<player_::Playing&>().get_state<player_::Playing::Song1&>().exit_counter == 1,
374             "Song1 exit not called correctly");
375         BOOST_CHECK_MESSAGE(
376             p.get_state<player_::Playing&>().start_next_song_counter == 0,
377             "submachine action not called correctly");
378
379         p.process_event(NextSong());
380         BOOST_CHECK_MESSAGE(p.current_state()[0] == 3,"Playing should be active"); //Playing
381         BOOST_CHECK_MESSAGE(p.get_state<player_::Playing&>().current_state()[0] == 2,"Song3 should be active");
382         BOOST_CHECK_MESSAGE(
383             p.get_state<player_::Playing&>().get_state<player_::Playing::Song3&>().entry_counter == 1,
384             "Song3 entry not called correctly");
385         BOOST_CHECK_MESSAGE(
386             p.get_state<player_::Playing&>().get_state<player_::Playing::Song2&>().exit_counter == 1,
387             "Song2 exit not called correctly");
388         BOOST_CHECK_MESSAGE(
389             p.get_state<player_::Playing&>().start_next_song_counter == 1,
390             "submachine action not called correctly");
391
392         p.process_event(PreviousSong());
393         BOOST_CHECK_MESSAGE(p.current_state()[0] == 3,"Playing should be active"); //Playing
394         BOOST_CHECK_MESSAGE(p.get_state<player_::Playing&>().current_state()[0] == 1,"Song2 should be active");
395         BOOST_CHECK_MESSAGE(
396             p.get_state<player_::Playing&>().get_state<player_::Playing::Song2&>().entry_counter == 2,
397             "Song2 entry not called correctly");
398         BOOST_CHECK_MESSAGE(
399             p.get_state<player_::Playing&>().get_state<player_::Playing::Song3&>().exit_counter == 1,
400             "Song3 exit not called correctly");
401         BOOST_CHECK_MESSAGE(
402             p.get_state<player_::Playing&>().start_prev_song_guard_counter == 1,
403             "submachine guard not called correctly");
404         //flags
405         BOOST_CHECK_MESSAGE(p.is_flag_active<PlayingPaused>() == true,"PlayingPaused should be active");
406         BOOST_CHECK_MESSAGE(p.is_flag_active<FirstSongPlaying>() == false,"FirstSongPlaying should not be active");
407
408         p.process_event(pause());
409         BOOST_CHECK_MESSAGE(p.current_state()[0] == 4,"Paused should be active"); //Paused
410         BOOST_CHECK_MESSAGE(p.get_state<player_::Playing&>().exit_counter == 1,"Playing exit not called correctly");
411         BOOST_CHECK_MESSAGE(p.get_state<player_::Paused&>().entry_counter == 1,"Paused entry not called correctly");
412         //flags
413         BOOST_CHECK_MESSAGE(p.is_flag_active<PlayingPaused>() == true,"PlayingPaused should be active");
414
415         // go back to Playing
416         p.process_event(end_pause());  
417         BOOST_CHECK_MESSAGE(p.current_state()[0] == 3,"Playing should be active"); //Playing
418         BOOST_CHECK_MESSAGE(p.get_state<player_::Paused&>().exit_counter == 1,"Paused exit not called correctly");
419         BOOST_CHECK_MESSAGE(p.get_state<player_::Playing&>().entry_counter == 2,"Playing entry not called correctly");
420
421         p.process_event(pause()); 
422         BOOST_CHECK_MESSAGE(p.current_state()[0] == 4,"Paused should be active"); //Paused
423         BOOST_CHECK_MESSAGE(p.get_state<player_::Playing&>().exit_counter == 2,"Playing exit not called correctly");
424         BOOST_CHECK_MESSAGE(p.get_state<player_::Paused&>().entry_counter == 2,"Paused entry not called correctly");
425
426         p.process_event(stop());  
427         BOOST_CHECK_MESSAGE(p.current_state()[0] == 0,"Stopped should be active"); //Stopped
428         BOOST_CHECK_MESSAGE(p.get_state<player_::Paused&>().exit_counter == 2,"Paused exit not called correctly");
429         BOOST_CHECK_MESSAGE(p.get_state<player_::Stopped&>().entry_counter == 2,"Stopped entry not called correctly");
430         //flags
431         BOOST_CHECK_MESSAGE(p.is_flag_active<PlayingPaused>() == false,"PlayingPaused should not be active");
432         BOOST_CHECK_MESSAGE(p.is_flag_active<CDLoaded>() == true,"CDLoaded should be active");
433         //BOOST_CHECK_MESSAGE(p.is_flag_active<CDLoaded,player::Flag_AND>() == false,"CDLoaded with AND should not be active");
434
435         p.process_event(stop());  
436         BOOST_CHECK_MESSAGE(p.current_state()[0] == 0,"Stopped should be active"); //Stopped
437         BOOST_CHECK_MESSAGE(p.get_state<player_::Stopped&>().exit_counter == 2,"Stopped exit not called correctly");
438         BOOST_CHECK_MESSAGE(p.get_state<player_::Stopped&>().entry_counter == 3,"Stopped entry not called correctly");
439
440         //test interrupt
441         BOOST_CHECK_MESSAGE(p.current_state()[1] == 5,"AllOk should be active"); //AllOk
442         p.process_event(error_found());
443         BOOST_CHECK_MESSAGE(p.current_state()[1] == 6,"ErrorMode should be active"); //ErrorMode
444         BOOST_CHECK_MESSAGE(p.get_state<player_::AllOk&>().exit_counter == 1,"AllOk exit not called correctly");
445         BOOST_CHECK_MESSAGE(p.get_state<player_::ErrorMode&>().entry_counter == 1,"ErrorMode entry not called correctly");
446
447         // try generating more events
448         p.process_event(play());
449         BOOST_CHECK_MESSAGE(p.current_state()[1] == 6,"ErrorMode should be active"); //ErrorMode
450         BOOST_CHECK_MESSAGE(p.get_state<player_::AllOk&>().exit_counter == 1,"AllOk exit not called correctly");
451         BOOST_CHECK_MESSAGE(p.get_state<player_::ErrorMode&>().entry_counter == 1,"ErrorMode entry not called correctly");
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         p.process_event(end_error());
457         BOOST_CHECK_MESSAGE(p.current_state()[1] == 5,"AllOk should be active"); //AllOk
458         BOOST_CHECK_MESSAGE(p.get_state<player_::ErrorMode&>().exit_counter == 1,"ErrorMode exit not called correctly");
459         BOOST_CHECK_MESSAGE(p.get_state<player_::AllOk&>().entry_counter == 2,"AllOk entry not called correctly");
460
461         p.process_event(play());
462         BOOST_CHECK_MESSAGE(p.current_state()[0] == 3,"Playing should be active"); //Playing
463         BOOST_CHECK_MESSAGE(p.get_state<player_::Stopped&>().exit_counter == 3,"Stopped exit not called correctly");
464         BOOST_CHECK_MESSAGE(p.get_state<player_::Playing&>().entry_counter == 3,"Playing entry not called correctly");
465
466         //test terminate
467         BOOST_CHECK_MESSAGE(p.current_state()[1] == 5,"AllOk should be active"); //AllOk
468         p.process_event(do_terminate());
469         BOOST_CHECK_MESSAGE(p.current_state()[1] == 7,"ErrorTerminate should be active"); //ErrorTerminate
470         BOOST_CHECK_MESSAGE(p.get_state<player_::AllOk&>().exit_counter == 2,"AllOk exit not called correctly");
471         BOOST_CHECK_MESSAGE(p.get_state<player_::ErrorTerminate&>().entry_counter == 1,"ErrorTerminate entry not called correctly");
472
473         // try generating more events
474         p.process_event(stop());
475         BOOST_CHECK_MESSAGE(p.current_state()[1] == 7,"ErrorTerminate should be active"); //ErrorTerminate
476         BOOST_CHECK_MESSAGE(p.get_state<player_::ErrorTerminate&>().exit_counter == 0,"ErrorTerminate exit not called correctly");
477         BOOST_CHECK_MESSAGE(p.current_state()[0] == 3,"Playing should be active"); //Playing
478         BOOST_CHECK_MESSAGE(p.get_state<player_::Playing&>().exit_counter == 2,"Playing exit not called correctly");
479         BOOST_CHECK_MESSAGE(p.get_state<player_::Stopped&>().entry_counter == 3,"Stopped entry not called correctly");
480
481         p.process_event(end_error());
482         BOOST_CHECK_MESSAGE(p.current_state()[1] == 7,"ErrorTerminate should be active"); //ErrorTerminate
483         BOOST_CHECK_MESSAGE(p.current_state()[0] == 3,"Playing should be active"); //Playing
484         BOOST_CHECK_MESSAGE(p.get_state<player_::Playing&>().exit_counter == 2,"Playing exit not called correctly");
485         BOOST_CHECK_MESSAGE(p.get_state<player_::Stopped&>().entry_counter == 3,"Stopped entry not called correctly");
486
487         p.process_event(stop());
488         BOOST_CHECK_MESSAGE(p.current_state()[1] == 7,"ErrorTerminate should be active"); //ErrorTerminate
489         BOOST_CHECK_MESSAGE(p.current_state()[0] == 3,"Playing should be active"); //Playing
490         BOOST_CHECK_MESSAGE(p.get_state<player_::Playing&>().exit_counter == 2,"Playing exit not called correctly");
491         BOOST_CHECK_MESSAGE(p.get_state<player_::Stopped&>().entry_counter == 3,"Stopped entry not called correctly");
492
493     }
494 }
495