OrthogonalDeferredEuml.cpp 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359
  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. #include <iostream>
  11. // back-end
  12. #include <boost/msm/back/state_machine.hpp>
  13. //front-end
  14. #include <boost/msm/front/state_machine_def.hpp>
  15. #include <boost/msm/front/euml/euml.hpp>
  16. #ifndef BOOST_MSM_NONSTANDALONE_TEST
  17. #define BOOST_TEST_MODULE MyTest
  18. #endif
  19. #include <boost/test/unit_test.hpp>
  20. namespace msm = boost::msm;
  21. namespace mpl = boost::mpl;
  22. using namespace boost::msm::front::euml;
  23. namespace
  24. {
  25. // events
  26. BOOST_MSM_EUML_EVENT(play)
  27. BOOST_MSM_EUML_EVENT(end_pause)
  28. BOOST_MSM_EUML_EVENT(stop)
  29. BOOST_MSM_EUML_EVENT(pause)
  30. BOOST_MSM_EUML_EVENT(open_close)
  31. BOOST_MSM_EUML_EVENT(next_song)
  32. BOOST_MSM_EUML_EVENT(previous_song)
  33. BOOST_MSM_EUML_EVENT(error_found)
  34. BOOST_MSM_EUML_EVENT(end_error)
  35. BOOST_MSM_EUML_EVENT(do_terminate)
  36. // Flags. Allow information about a property of the current state
  37. BOOST_MSM_EUML_FLAG(PlayingPaused)
  38. BOOST_MSM_EUML_FLAG(CDLoaded)
  39. BOOST_MSM_EUML_FLAG(FirstSongPlaying)
  40. // A "complicated" event type that carries some data.
  41. BOOST_MSM_EUML_DECLARE_ATTRIBUTE(std::string,cd_name)
  42. BOOST_MSM_EUML_ATTRIBUTES((attributes_ << cd_name ), cd_detected_attributes)
  43. BOOST_MSM_EUML_EVENT_WITH_ATTRIBUTES(cd_detected,cd_detected_attributes)
  44. //states
  45. BOOST_MSM_EUML_DECLARE_ATTRIBUTE(unsigned int,entry_counter)
  46. BOOST_MSM_EUML_DECLARE_ATTRIBUTE(unsigned int,exit_counter)
  47. BOOST_MSM_EUML_STATE(( ++state_(entry_counter),++state_(exit_counter),
  48. attributes_ << entry_counter << exit_counter, configure_ << play),Empty)
  49. BOOST_MSM_EUML_STATE(( ++state_(entry_counter),++state_(exit_counter),
  50. attributes_ << entry_counter << exit_counter, configure_<< CDLoaded << play),Open)
  51. BOOST_MSM_EUML_STATE(( ++state_(entry_counter),++state_(exit_counter),
  52. attributes_ << entry_counter << exit_counter, configure_<< CDLoaded),Stopped)
  53. BOOST_MSM_EUML_STATE(( ++state_(entry_counter),++state_(exit_counter),
  54. attributes_ << entry_counter << exit_counter, configure_<< CDLoaded << PlayingPaused),Paused)
  55. BOOST_MSM_EUML_STATE(( ++state_(entry_counter),++state_(exit_counter),attributes_ << entry_counter << exit_counter),AllOk)
  56. BOOST_MSM_EUML_TERMINATE_STATE(( ++state_(entry_counter),++state_(exit_counter),attributes_ << entry_counter << exit_counter),
  57. ErrorTerminate)
  58. BOOST_MSM_EUML_INTERRUPT_STATE(( end_error,++state_(entry_counter),++state_(exit_counter),attributes_ << entry_counter << exit_counter),
  59. ErrorMode)
  60. // Playing is now a state machine itself.
  61. BOOST_MSM_EUML_DECLARE_ATTRIBUTE(unsigned int,start_next_song_counter)
  62. BOOST_MSM_EUML_DECLARE_ATTRIBUTE(unsigned int,start_prev_song_guard_counter)
  63. BOOST_MSM_EUML_STATE(( ++state_(entry_counter),++state_(exit_counter),
  64. attributes_ << entry_counter << exit_counter, configure_<< FirstSongPlaying ),Song1)
  65. BOOST_MSM_EUML_STATE(( ++state_(entry_counter),++state_(exit_counter),attributes_ << entry_counter << exit_counter),Song2)
  66. BOOST_MSM_EUML_STATE(( ++state_(entry_counter),++state_(exit_counter),attributes_ << entry_counter << exit_counter),Song3)
  67. // Playing has a transition table
  68. BOOST_MSM_EUML_TRANSITION_TABLE((
  69. // +------------------------------------------------------------------------------+
  70. Song2 == Song1 + next_song ,
  71. Song1 == Song2 + previous_song [True_()] / ++fsm_(start_prev_song_guard_counter) ,
  72. Song3 == Song2 + next_song / ++fsm_(start_next_song_counter) ,
  73. Song2 == Song3 + previous_song [True_()] / ++fsm_(start_prev_song_guard_counter)
  74. // +------------------------------------------------------------------------------+
  75. ),playing_transition_table )
  76. BOOST_MSM_EUML_DECLARE_STATE_MACHINE( (playing_transition_table, //STT
  77. init_ << Song1, // Init State
  78. ++state_(entry_counter), // Entry
  79. ++state_(exit_counter), // Exit
  80. attributes_ << entry_counter << exit_counter
  81. << start_next_song_counter
  82. << start_prev_song_guard_counter, // Attributes
  83. configure_<< PlayingPaused << CDLoaded //flags
  84. ),Playing_)
  85. // back-end
  86. typedef msm::back::state_machine<Playing_> Playing_type;
  87. Playing_type const Playing;
  88. //fsm
  89. BOOST_MSM_EUML_DECLARE_ATTRIBUTE(unsigned int,start_playback_counter)
  90. BOOST_MSM_EUML_DECLARE_ATTRIBUTE(unsigned int,can_close_drawer_counter)
  91. BOOST_MSM_EUML_DECLARE_ATTRIBUTE(unsigned int,report_error_counter)
  92. BOOST_MSM_EUML_DECLARE_ATTRIBUTE(unsigned int,report_end_error_counter)
  93. BOOST_MSM_EUML_ACTION(No_Transition)
  94. {
  95. template <class FSM,class Event>
  96. void operator()(Event const&,FSM&,int)
  97. {
  98. BOOST_FAIL("no_transition called!");
  99. }
  100. };
  101. BOOST_MSM_EUML_TRANSITION_TABLE((
  102. Playing == Stopped + play / ++fsm_(start_playback_counter),
  103. Playing == Paused + end_pause ,
  104. // +------------------------------------------------------------------------------+
  105. Empty == Open + open_close / ++fsm_(can_close_drawer_counter),
  106. // +------------------------------------------------------------------------------+
  107. Open == Empty + open_close ,
  108. Open == Paused + open_close ,
  109. Open == Stopped + open_close ,
  110. Open == Playing + open_close ,
  111. // +------------------------------------------------------------------------------+
  112. Paused == Playing + pause ,
  113. // +------------------------------------------------------------------------------+
  114. Stopped == Playing + stop ,
  115. Stopped == Paused + stop ,
  116. Stopped == Empty + cd_detected ,
  117. Stopped == Stopped + stop ,
  118. ErrorMode == AllOk + error_found / ++fsm_(report_error_counter),
  119. AllOk == ErrorMode+ end_error / ++fsm_(report_end_error_counter),
  120. ErrorTerminate== AllOk +do_terminate
  121. // +------------------------------------------------------------------------------+
  122. ),transition_table)
  123. BOOST_MSM_EUML_DECLARE_STATE_MACHINE(( transition_table, //STT
  124. init_ << Empty << AllOk, // Init State
  125. no_action, // Entry
  126. no_action, // Exit
  127. attributes_ << start_playback_counter << can_close_drawer_counter
  128. << report_error_counter << report_end_error_counter, // Attributes
  129. configure_ << no_configure_, // configuration
  130. No_Transition // no_transition handler
  131. ),
  132. player_) //fsm name
  133. // Pick a back-end
  134. typedef msm::back::state_machine<player_> player;
  135. //static char const* const state_names[] = { "Stopped", "Paused","Open", "Empty", "Playing" ,"AllOk","ErrorMode","ErrorTerminate" };
  136. BOOST_AUTO_TEST_CASE( my_test )
  137. {
  138. player p;
  139. // needed to start the highest-level SM. This will call on_entry and mark the start of the SM
  140. p.start();
  141. // test deferred event
  142. // deferred in Empty and Open, will be handled only after event cd_detected
  143. p.process_event(play);
  144. BOOST_CHECK_MESSAGE(p.current_state()[0] == 3,"Empty should be active"); //Empty
  145. BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(Open)&>().get_attribute(exit_counter) == 0,
  146. "Open exit not called correctly");
  147. BOOST_CHECK_MESSAGE(p.get_state<Playing_type&>().get_attribute(entry_counter) == 0,"Playing entry not called correctly");
  148. BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(Empty)&>().get_attribute(entry_counter) == 1,
  149. "Empty entry not called correctly");
  150. //flags
  151. BOOST_CHECK_MESSAGE(p.is_flag_active<BOOST_MSM_EUML_FLAG_NAME(CDLoaded)>() == false,"CDLoaded should not be active");
  152. p.process_event(open_close);
  153. BOOST_CHECK_MESSAGE(p.current_state()[0] == 2,"Open should be active"); //Open
  154. BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(Empty)&>().get_attribute(exit_counter) == 1,
  155. "Empty exit not called correctly");
  156. BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(Open)&>().get_attribute(entry_counter) == 1,
  157. "Open entry not called correctly");
  158. p.process_event(open_close);
  159. BOOST_CHECK_MESSAGE(p.current_state()[0] == 3,"Empty should be active"); //Empty
  160. BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(Open)&>().get_attribute(exit_counter) == 1,
  161. "Open exit not called correctly");
  162. BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(Empty)&>().get_attribute(entry_counter) == 2,
  163. "Empty entry not called correctly");
  164. BOOST_CHECK_MESSAGE(p.get_attribute(can_close_drawer_counter) == 1,"guard not called correctly");
  165. //deferred event should have been processed
  166. p.process_event(cd_detected("louie, louie"));
  167. BOOST_CHECK_MESSAGE(p.current_state()[0] == 4,"Playing should be active"); //Playing
  168. BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(Empty)&>().get_attribute(exit_counter) == 2,
  169. "Empty exit not called correctly");
  170. BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(Stopped)&>().get_attribute(entry_counter) == 1,
  171. "Stopped entry not called correctly");
  172. BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(Stopped)&>().get_attribute(exit_counter) == 1,
  173. "Stopped exit not called correctly");
  174. BOOST_CHECK_MESSAGE(p.get_state<Playing_type&>().get_attribute(entry_counter) == 1,"Playing entry not called correctly");
  175. BOOST_CHECK_MESSAGE(p.get_attribute(start_playback_counter) == 1,"action not called correctly");
  176. BOOST_CHECK_MESSAGE(p.get_state<Playing_type&>().current_state()[0] == 0,"Song1 should be active");
  177. BOOST_CHECK_MESSAGE(
  178. p.get_state<Playing_type&>().get_state<BOOST_MSM_EUML_STATE_NAME(Song1)&>().get_attribute(entry_counter) == 1,
  179. "Song1 entry not called correctly");
  180. //flags
  181. BOOST_CHECK_MESSAGE(p.is_flag_active<BOOST_MSM_EUML_FLAG_NAME(PlayingPaused)>() == true,"PlayingPaused should be active");
  182. BOOST_CHECK_MESSAGE(p.is_flag_active<BOOST_MSM_EUML_FLAG_NAME(FirstSongPlaying)>() == true,"FirstSongPlaying should be active");
  183. p.process_event(next_song);
  184. BOOST_CHECK_MESSAGE(p.current_state()[0] == 4,"Playing should be active"); //Playing
  185. BOOST_CHECK_MESSAGE(p.get_state<Playing_type&>().current_state()[0] == 1,"Song2 should be active");
  186. BOOST_CHECK_MESSAGE(
  187. p.get_state<Playing_type&>().get_state<BOOST_MSM_EUML_STATE_NAME(Song2)&>().get_attribute(entry_counter) == 1,
  188. "Song2 entry not called correctly");
  189. BOOST_CHECK_MESSAGE(
  190. p.get_state<Playing_type&>().get_state<BOOST_MSM_EUML_STATE_NAME(Song1)&>().get_attribute(exit_counter) == 1,
  191. "Song1 exit not called correctly");
  192. BOOST_CHECK_MESSAGE(
  193. p.get_state<Playing_type&>().get_attribute(start_next_song_counter) == 0,
  194. "submachine action not called correctly");
  195. p.process_event(next_song);
  196. BOOST_CHECK_MESSAGE(p.current_state()[0] == 4,"Playing should be active"); //Playing
  197. BOOST_CHECK_MESSAGE(p.get_state<Playing_type&>().current_state()[0] == 2,"Song3 should be active");
  198. BOOST_CHECK_MESSAGE(
  199. p.get_state<Playing_type&>().get_state<BOOST_MSM_EUML_STATE_NAME(Song3)&>().get_attribute(entry_counter) == 1,
  200. "Song3 entry not called correctly");
  201. BOOST_CHECK_MESSAGE(
  202. p.get_state<Playing_type&>().get_state<BOOST_MSM_EUML_STATE_NAME(Song2)&>().get_attribute(exit_counter) == 1,
  203. "Song2 exit not called correctly");
  204. BOOST_CHECK_MESSAGE(
  205. p.get_state<Playing_type&>().get_attribute(start_next_song_counter) == 1,
  206. "submachine action not called correctly");
  207. p.process_event(previous_song);
  208. BOOST_CHECK_MESSAGE(p.current_state()[0] == 4,"Playing should be active"); //Playing
  209. BOOST_CHECK_MESSAGE(p.get_state<Playing_type&>().current_state()[0] == 1,"Song2 should be active");
  210. BOOST_CHECK_MESSAGE(
  211. p.get_state<Playing_type&>().get_state<BOOST_MSM_EUML_STATE_NAME(Song2)&>().get_attribute(entry_counter) == 2,
  212. "Song2 entry not called correctly");
  213. BOOST_CHECK_MESSAGE(
  214. p.get_state<Playing_type&>().get_state<BOOST_MSM_EUML_STATE_NAME(Song3)&>().get_attribute(exit_counter) == 1,
  215. "Song3 exit not called correctly");
  216. BOOST_CHECK_MESSAGE(
  217. p.get_state<Playing_type&>().get_attribute(start_prev_song_guard_counter) == 1,
  218. "submachine guard not called correctly");
  219. //flags
  220. BOOST_CHECK_MESSAGE(p.is_flag_active<BOOST_MSM_EUML_FLAG_NAME(PlayingPaused)>() == true,"PlayingPaused should be active");
  221. BOOST_CHECK_MESSAGE(p.is_flag_active<BOOST_MSM_EUML_FLAG_NAME(FirstSongPlaying)>() == false,"FirstSongPlaying should not be active");
  222. p.process_event(pause());
  223. BOOST_CHECK_MESSAGE(p.current_state()[0] == 1,"Paused should be active"); //Paused
  224. BOOST_CHECK_MESSAGE(p.get_state<Playing_type&>().get_attribute(exit_counter) == 1,"Playing exit not called correctly");
  225. BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(Paused)&>().get_attribute(entry_counter) == 1,
  226. "Paused entry not called correctly");
  227. //flags
  228. BOOST_CHECK_MESSAGE(p.is_flag_active<BOOST_MSM_EUML_FLAG_NAME(PlayingPaused)>() == true,"PlayingPaused should be active");
  229. // go back to Playing
  230. p.process_event(end_pause);
  231. BOOST_CHECK_MESSAGE(p.current_state()[0] == 4,"Playing should be active"); //Playing
  232. BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(Paused)&>().get_attribute(exit_counter) == 1,
  233. "Paused exit not called correctly");
  234. BOOST_CHECK_MESSAGE(p.get_state<Playing_type&>().get_attribute(entry_counter) == 2,"Playing entry not called correctly");
  235. p.process_event(pause);
  236. BOOST_CHECK_MESSAGE(p.current_state()[0] == 1,"Paused should be active"); //Paused
  237. BOOST_CHECK_MESSAGE(p.get_state<Playing_type&>().get_attribute(exit_counter) == 2,"Playing exit not called correctly");
  238. BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(Paused)&>().get_attribute(entry_counter) == 2,
  239. "Paused entry not called correctly");
  240. p.process_event(stop);
  241. BOOST_CHECK_MESSAGE(p.current_state()[0] == 0,"Stopped should be active"); //Stopped
  242. BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(Paused)&>().get_attribute(exit_counter) == 2,
  243. "Paused exit not called correctly");
  244. BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(Stopped)&>().get_attribute(entry_counter) == 2,
  245. "Stopped entry not called correctly");
  246. //flags
  247. BOOST_CHECK_MESSAGE(p.is_flag_active<BOOST_MSM_EUML_FLAG_NAME(PlayingPaused)>() == false,"PlayingPaused should not be active");
  248. BOOST_CHECK_MESSAGE(p.is_flag_active<BOOST_MSM_EUML_FLAG_NAME(CDLoaded)>() == true,"CDLoaded should be active");
  249. //BOOST_CHECK_MESSAGE(p.is_flag_active<BOOST_MSM_EUML_FLAG_NAME(CDLoaded),player::Flag_AND>() == false,"CDLoaded with AND should not be active");
  250. p.process_event(stop);
  251. BOOST_CHECK_MESSAGE(p.current_state()[0] == 0,"Stopped should be active"); //Stopped
  252. BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(Stopped)&>().get_attribute(exit_counter) == 2,
  253. "Stopped exit not called correctly");
  254. BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(Stopped)&>().get_attribute(entry_counter) == 3,
  255. "Stopped entry not called correctly");
  256. //test interrupt
  257. BOOST_CHECK_MESSAGE(p.current_state()[1] == 5,"AllOk should be active"); //AllOk
  258. p.process_event(error_found);
  259. BOOST_CHECK_MESSAGE(p.current_state()[1] == 6,"ErrorMode should be active"); //ErrorMode
  260. BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(AllOk)&>().get_attribute(exit_counter) == 1,
  261. "AllOk exit not called correctly");
  262. BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(ErrorMode)&>().get_attribute(entry_counter) == 1,
  263. "ErrorMode entry not called correctly");
  264. // try generating more events
  265. p.process_event(play);
  266. BOOST_CHECK_MESSAGE(p.current_state()[1] == 6,"ErrorMode should be active"); //ErrorMode
  267. BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(AllOk)&>().get_attribute(exit_counter) == 1,
  268. "AllOk exit not called correctly");
  269. BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(ErrorMode)&>().get_attribute(entry_counter) == 1,
  270. "ErrorMode entry not called correctly");
  271. BOOST_CHECK_MESSAGE(p.current_state()[0] == 0,"Stopped should be active"); //Stopped
  272. BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(Stopped)&>().get_attribute(exit_counter) == 2,
  273. "Stopped exit not called correctly");
  274. BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(Stopped)&>().get_attribute(entry_counter) == 3,
  275. "Stopped entry not called correctly");
  276. p.process_event(end_error);
  277. BOOST_CHECK_MESSAGE(p.current_state()[1] == 5,"AllOk should be active"); //AllOk
  278. BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(ErrorMode)&>().get_attribute(exit_counter) == 1,
  279. "ErrorMode exit not called correctly");
  280. BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(AllOk)&>().get_attribute(entry_counter) == 2,
  281. "AllOk entry not called correctly");
  282. p.process_event(play);
  283. BOOST_CHECK_MESSAGE(p.current_state()[0] == 4,"Playing should be active"); //Playing
  284. BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(Stopped)&>().get_attribute(exit_counter) == 3,
  285. "Stopped exit not called correctly");
  286. BOOST_CHECK_MESSAGE(p.get_state<Playing_type&>().get_attribute(entry_counter) == 3,"Playing entry not called correctly");
  287. //test terminate
  288. BOOST_CHECK_MESSAGE(p.current_state()[1] == 5,"AllOk should be active"); //AllOk
  289. p.process_event(do_terminate);
  290. BOOST_CHECK_MESSAGE(p.current_state()[1] == 7,"ErrorTerminate should be active"); //ErrorTerminate
  291. BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(AllOk)&>().get_attribute(exit_counter) == 2,
  292. "AllOk exit not called correctly");
  293. BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(ErrorTerminate)&>().get_attribute(entry_counter) == 1,
  294. "ErrorTerminate entry not called correctly");
  295. // try generating more events
  296. p.process_event(stop);
  297. BOOST_CHECK_MESSAGE(p.current_state()[1] == 7,"ErrorTerminate should be active"); //ErrorTerminate
  298. BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(ErrorTerminate)&>().get_attribute(exit_counter) == 0,
  299. "ErrorTerminate exit not called correctly");
  300. BOOST_CHECK_MESSAGE(p.current_state()[0] == 4,"Playing should be active"); //Playing
  301. BOOST_CHECK_MESSAGE(p.get_state<Playing_type&>().get_attribute(exit_counter) == 2,"Playing exit not called correctly");
  302. BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(Stopped)&>().get_attribute(entry_counter) == 3,
  303. "Stopped entry not called correctly");
  304. p.process_event(end_error());
  305. BOOST_CHECK_MESSAGE(p.current_state()[1] == 7,"ErrorTerminate should be active"); //ErrorTerminate
  306. BOOST_CHECK_MESSAGE(p.current_state()[0] == 4,"Playing should be active"); //Playing
  307. BOOST_CHECK_MESSAGE(p.get_state<Playing_type&>().get_attribute(exit_counter) == 2,"Playing exit not called correctly");
  308. BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(Stopped)&>().get_attribute(entry_counter) == 3,
  309. "Stopped entry not called correctly");
  310. p.process_event(stop());
  311. BOOST_CHECK_MESSAGE(p.current_state()[1] == 7,"ErrorTerminate should be active"); //ErrorTerminate
  312. BOOST_CHECK_MESSAGE(p.current_state()[0] == 4,"Playing should be active"); //Playing
  313. BOOST_CHECK_MESSAGE(p.get_state<Playing_type&>().get_attribute(exit_counter) == 2,"Playing exit not called correctly");
  314. BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(Stopped)&>().get_attribute(entry_counter) == 3,
  315. "Stopped entry not called correctly");
  316. }
  317. }