SimpleEuml2.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197
  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. #include <boost/msm/back/state_machine.hpp>
  12. #include <boost/msm/front/euml/euml.hpp>
  13. #ifndef BOOST_MSM_NONSTANDALONE_TEST
  14. #define BOOST_TEST_MODULE MyTest
  15. #endif
  16. #include <boost/test/unit_test.hpp>
  17. using namespace std;
  18. using namespace boost::msm::front::euml;
  19. namespace msm = boost::msm;
  20. namespace
  21. {
  22. // A "complicated" event type that carries some data.
  23. enum DiskTypeEnum
  24. {
  25. DISK_CD=0,
  26. DISK_DVD=1
  27. };
  28. // events
  29. BOOST_MSM_EUML_EVENT(play)
  30. BOOST_MSM_EUML_EVENT(end_pause)
  31. BOOST_MSM_EUML_EVENT(stop)
  32. BOOST_MSM_EUML_EVENT(pause)
  33. BOOST_MSM_EUML_EVENT(open_close)
  34. // A "complicated" event type that carries some data.
  35. BOOST_MSM_EUML_DECLARE_ATTRIBUTE(std::string,cd_name)
  36. BOOST_MSM_EUML_DECLARE_ATTRIBUTE(DiskTypeEnum,cd_type)
  37. BOOST_MSM_EUML_ATTRIBUTES((attributes_ << cd_name << cd_type ), cd_detected_attributes)
  38. BOOST_MSM_EUML_EVENT_WITH_ATTRIBUTES(cd_detected,cd_detected_attributes)
  39. //states
  40. BOOST_MSM_EUML_DECLARE_ATTRIBUTE(unsigned int,entry_counter)
  41. BOOST_MSM_EUML_DECLARE_ATTRIBUTE(unsigned int,exit_counter)
  42. BOOST_MSM_EUML_STATE(( ++state_(entry_counter),++state_(exit_counter),attributes_ << entry_counter << exit_counter),Empty)
  43. BOOST_MSM_EUML_STATE(( ++state_(entry_counter),++state_(exit_counter),attributes_ << entry_counter << exit_counter),Open)
  44. BOOST_MSM_EUML_STATE(( ++state_(entry_counter),++state_(exit_counter),attributes_ << entry_counter << exit_counter),Stopped)
  45. BOOST_MSM_EUML_STATE(( ++state_(entry_counter),++state_(exit_counter),attributes_ << entry_counter << exit_counter),Playing)
  46. BOOST_MSM_EUML_STATE(( ++state_(entry_counter),++state_(exit_counter),attributes_ << entry_counter << exit_counter),Paused)
  47. //fsm
  48. BOOST_MSM_EUML_DECLARE_ATTRIBUTE(unsigned int,start_playback_counter)
  49. BOOST_MSM_EUML_DECLARE_ATTRIBUTE(unsigned int,can_close_drawer_counter)
  50. BOOST_MSM_EUML_DECLARE_ATTRIBUTE(unsigned int,test_fct_counter)
  51. BOOST_MSM_EUML_ACTION(No_Transition)
  52. {
  53. template <class FSM,class Event>
  54. void operator()(Event const&,FSM&,int)
  55. {
  56. BOOST_FAIL("no_transition called!");
  57. }
  58. };
  59. BOOST_MSM_EUML_ACTION(good_disk_format)
  60. {
  61. template <class FSM,class EVT,class SourceState,class TargetState>
  62. bool operator()(EVT const& evt,FSM&,SourceState& ,TargetState& )
  63. {
  64. if (evt.get_attribute(cd_type)!=DISK_CD)
  65. {
  66. return false;
  67. }
  68. return true;
  69. }
  70. };
  71. BOOST_MSM_EUML_TRANSITION_TABLE((
  72. Stopped + play / (++fsm_(start_playback_counter),++fsm_(test_fct_counter)) == Playing,
  73. Paused + end_pause == Playing,
  74. // +------------------------------------------------------------------------------+
  75. Open + open_close / ++fsm_(can_close_drawer_counter) == Empty,
  76. // +------------------------------------------------------------------------------+
  77. Empty + open_close == Open,
  78. Paused + open_close == Open,
  79. Stopped + open_close == Open,
  80. Playing + open_close == Open,
  81. // +------------------------------------------------------------------------------+
  82. Playing + pause == Paused,
  83. // +------------------------------------------------------------------------------+
  84. Playing + stop == Stopped,
  85. Paused + stop == Stopped,
  86. Empty + cd_detected [good_disk_format ||
  87. (event_(cd_type)==Int_<DISK_CD>())] / process_(play) == Stopped,
  88. Stopped + stop == Stopped
  89. // +------------------------------------------------------------------------------+
  90. ),transition_table)
  91. BOOST_MSM_EUML_DECLARE_STATE_MACHINE(( transition_table, //STT
  92. init_ << Empty, // Init State
  93. no_action, // Entry
  94. no_action, // Exit
  95. attributes_ << start_playback_counter
  96. << can_close_drawer_counter << test_fct_counter, // Attributes
  97. configure_ << no_configure_, // configuration
  98. No_Transition // no_transition handler
  99. ),
  100. player_) //fsm name
  101. typedef msm::back::state_machine<player_> player;
  102. // static char const* const state_names[] = { "Stopped", "Paused", "Open", "Empty", "Playing" };
  103. BOOST_AUTO_TEST_CASE( my_test )
  104. {
  105. player p;
  106. p.start();
  107. BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(Empty)&>().get_attribute(entry_counter) == 1,
  108. "Empty entry not called correctly");
  109. p.process_event(open_close());
  110. BOOST_CHECK_MESSAGE(p.current_state()[0] == 2,"Open should be active"); //Open
  111. BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(Empty)&>().get_attribute(exit_counter) == 1,
  112. "Empty exit not called correctly");
  113. BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(Open)&>().get_attribute(entry_counter) == 1,
  114. "Open entry not called correctly");
  115. p.process_event(open_close());
  116. BOOST_CHECK_MESSAGE(p.current_state()[0] == 3,"Empty should be active"); //Empty
  117. BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(Open)&>().get_attribute(exit_counter) == 1,
  118. "Open exit not called correctly");
  119. BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(Empty)&>().get_attribute(entry_counter) == 2,
  120. "Empty entry not called correctly");
  121. BOOST_CHECK_MESSAGE(p.get_attribute(can_close_drawer_counter) == 1,"guard not called correctly");
  122. p.process_event(
  123. cd_detected("louie, louie",DISK_DVD));
  124. BOOST_CHECK_MESSAGE(p.current_state()[0] == 3,"Empty should be active"); //Empty
  125. BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(Open)&>().get_attribute(exit_counter) == 1,
  126. "Open exit not called correctly");
  127. BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(Empty)&>().get_attribute(entry_counter) == 2,
  128. "Empty entry not called correctly");
  129. p.process_event(
  130. cd_detected("louie, louie",DISK_CD));
  131. BOOST_CHECK_MESSAGE(p.current_state()[0] == 4,"Playing should be active"); //Playing
  132. BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(Empty)&>().get_attribute(exit_counter) == 2,
  133. "Empty exit not called correctly");
  134. BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(Stopped)&>().get_attribute(entry_counter) == 1,
  135. "Stopped entry not called correctly");
  136. BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(Stopped)&>().get_attribute(exit_counter) == 1,
  137. "Stopped exit not called correctly");
  138. BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(Playing)&>().get_attribute(entry_counter) == 1,
  139. "Playing entry not called correctly");
  140. BOOST_CHECK_MESSAGE(p.get_attribute(start_playback_counter) == 1,"action not called correctly");
  141. BOOST_CHECK_MESSAGE(p.get_attribute(test_fct_counter) == 1,"action not called correctly");
  142. p.process_event(pause());
  143. BOOST_CHECK_MESSAGE(p.current_state()[0] == 1,"Paused should be active"); //Paused
  144. BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(Playing)&>().get_attribute(exit_counter) == 1,
  145. "Playing exit not called correctly");
  146. BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(Paused)&>().get_attribute(entry_counter) == 1,
  147. "Paused entry not called correctly");
  148. // go back to Playing
  149. p.process_event(end_pause());
  150. BOOST_CHECK_MESSAGE(p.current_state()[0] == 4,"Playing should be active"); //Playing
  151. BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(Paused)&>().get_attribute(exit_counter) == 1,
  152. "Paused exit not called correctly");
  153. BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(Playing)&>().get_attribute(entry_counter) == 2,
  154. "Playing entry not called correctly");
  155. p.process_event(pause());
  156. BOOST_CHECK_MESSAGE(p.current_state()[0] == 1,"Paused should be active"); //Paused
  157. BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(Playing)&>().get_attribute(exit_counter) == 2,
  158. "Playing exit not called correctly");
  159. BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(Paused)&>().get_attribute(entry_counter) == 2,
  160. "Paused entry not called correctly");
  161. p.process_event(stop());
  162. BOOST_CHECK_MESSAGE(p.current_state()[0] == 0,"Stopped should be active"); //Stopped
  163. BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(Paused)&>().get_attribute(exit_counter) == 2,
  164. "Paused exit not called correctly");
  165. BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(Stopped)&>().get_attribute(entry_counter) == 2,
  166. "Stopped entry not called correctly");
  167. p.process_event(stop());
  168. BOOST_CHECK_MESSAGE(p.current_state()[0] == 0,"Stopped should be active"); //Stopped
  169. BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(Stopped)&>().get_attribute(exit_counter) == 2,
  170. "Stopped exit not called correctly");
  171. BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(Stopped)&>().get_attribute(entry_counter) == 3,
  172. "Stopped entry not called correctly");
  173. }
  174. }