Anonymous.cpp 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184
  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. #ifndef BOOST_MSM_NONSTANDALONE_TEST
  16. #define BOOST_TEST_MODULE MyTest
  17. #endif
  18. #include <boost/test/unit_test.hpp>
  19. namespace msm = boost::msm;
  20. namespace mpl = boost::mpl;
  21. using namespace boost::msm::front;
  22. namespace
  23. {
  24. // events
  25. struct event1 {};
  26. // front-end: define the FSM structure
  27. struct my_machine_ : public msm::front::state_machine_def<my_machine_>
  28. {
  29. unsigned int state2_to_state3_counter;
  30. unsigned int state3_to_state4_counter;
  31. unsigned int always_true_counter;
  32. unsigned int always_false_counter;
  33. my_machine_():
  34. state2_to_state3_counter(0),
  35. state3_to_state4_counter(0),
  36. always_true_counter(0),
  37. always_false_counter(0)
  38. {}
  39. // The list of FSM states
  40. struct State1 : public msm::front::state<>
  41. {
  42. template <class Event,class FSM>
  43. void on_entry(Event const&,FSM& ) {++entry_counter;}
  44. template <class Event,class FSM>
  45. void on_exit(Event const&,FSM& ) {++exit_counter;}
  46. int entry_counter;
  47. int exit_counter;
  48. };
  49. struct State2 : public msm::front::state<>
  50. {
  51. template <class Event,class FSM>
  52. void on_entry(Event const&,FSM& ) {++entry_counter;}
  53. template <class Event,class FSM>
  54. void on_exit(Event const&,FSM& ) {++exit_counter;}
  55. int entry_counter;
  56. int exit_counter;
  57. };
  58. struct State3 : public msm::front::state<>
  59. {
  60. template <class Event,class FSM>
  61. void on_entry(Event const&,FSM& ) {++entry_counter;}
  62. template <class Event,class FSM>
  63. void on_exit(Event const&,FSM& ) {++exit_counter;}
  64. int entry_counter;
  65. int exit_counter;
  66. };
  67. struct State4 : public msm::front::state<>
  68. {
  69. template <class Event,class FSM>
  70. void on_entry(Event const&,FSM& ) {++entry_counter;}
  71. template <class Event,class FSM>
  72. void on_exit(Event const&,FSM& ) {++exit_counter;}
  73. int entry_counter;
  74. int exit_counter;
  75. };
  76. // the initial state of the player SM. Must be defined
  77. typedef State1 initial_state;
  78. // transition actions
  79. void State2ToState3(none const&) { ++state2_to_state3_counter; }
  80. void State3ToState4(none const&) { ++state3_to_state4_counter; }
  81. // guard conditions
  82. bool always_true(none const& )
  83. {
  84. ++always_true_counter;
  85. return true;
  86. }
  87. bool always_false(none const& )
  88. {
  89. ++always_false_counter;
  90. return false;
  91. }
  92. typedef my_machine_ p; // makes transition table cleaner
  93. // Transition table for player
  94. struct transition_table : mpl::vector<
  95. // Start Event Next Action Guard
  96. // +---------+-------------+---------+---------------------+----------------------+
  97. _row < State1 , none , State2 >,
  98. a_row < State2 , none , State3 , &p::State2ToState3 >,
  99. // +---------+-------------+---------+---------------------+----------------------+
  100. row < State3 , none , State4 , &p::State3ToState4 , &p::always_true >,
  101. g_row < State3 , none , State4 , &p::always_false >,
  102. _row < State4 , event1 , State1 >
  103. // +---------+-------------+---------+---------------------+----------------------+
  104. > {};
  105. // Replaces the default no-transition response.
  106. template <class FSM,class Event>
  107. void no_transition(Event const&, FSM&,int)
  108. {
  109. BOOST_FAIL("no_transition called!");
  110. }
  111. // init counters
  112. template <class Event,class FSM>
  113. void on_entry(Event const&,FSM& fsm)
  114. {
  115. fsm.template get_state<my_machine_::State1&>().entry_counter=0;
  116. fsm.template get_state<my_machine_::State1&>().exit_counter=0;
  117. fsm.template get_state<my_machine_::State2&>().entry_counter=0;
  118. fsm.template get_state<my_machine_::State2&>().exit_counter=0;
  119. fsm.template get_state<my_machine_::State3&>().entry_counter=0;
  120. fsm.template get_state<my_machine_::State3&>().exit_counter=0;
  121. fsm.template get_state<my_machine_::State4&>().entry_counter=0;
  122. fsm.template get_state<my_machine_::State4&>().exit_counter=0;
  123. }
  124. };
  125. // Pick a back-end
  126. typedef msm::back::state_machine<my_machine_> my_machine;
  127. //static char const* const state_names[] = { "State1", "State2", "State3", "State4" };
  128. BOOST_AUTO_TEST_CASE( my_test )
  129. {
  130. my_machine p;
  131. // needed to start the highest-level SM. This will call on_entry and mark the start of the SM
  132. // in this case it will also immediately trigger all anonymous transitions
  133. p.start();
  134. BOOST_CHECK_MESSAGE(p.current_state()[0] == 3,"State4 should be active"); //State4
  135. BOOST_CHECK_MESSAGE(p.get_state<my_machine_::State1&>().exit_counter == 1,"State1 exit not called correctly");
  136. BOOST_CHECK_MESSAGE(p.get_state<my_machine_::State1&>().entry_counter == 1,"State1 entry not called correctly");
  137. BOOST_CHECK_MESSAGE(p.get_state<my_machine_::State2&>().exit_counter == 1,"State2 exit not called correctly");
  138. BOOST_CHECK_MESSAGE(p.get_state<my_machine_::State2&>().entry_counter == 1,"State2 entry not called correctly");
  139. BOOST_CHECK_MESSAGE(p.get_state<my_machine_::State3&>().exit_counter == 1,"State3 exit not called correctly");
  140. BOOST_CHECK_MESSAGE(p.get_state<my_machine_::State3&>().entry_counter == 1,"State3 entry not called correctly");
  141. BOOST_CHECK_MESSAGE(p.get_state<my_machine_::State4&>().entry_counter == 1,"State4 entry not called correctly");
  142. BOOST_CHECK_MESSAGE(p.always_true_counter == 1,"guard not called correctly");
  143. BOOST_CHECK_MESSAGE(p.always_false_counter == 1,"guard not called correctly");
  144. BOOST_CHECK_MESSAGE(p.state2_to_state3_counter == 1,"action not called correctly");
  145. BOOST_CHECK_MESSAGE(p.state3_to_state4_counter == 1,"action not called correctly");
  146. // this event will bring us back to the initial state and thus, a new "loop" will be started
  147. p.process_event(event1());
  148. BOOST_CHECK_MESSAGE(p.current_state()[0] == 3,"State4 should be active"); //State4
  149. BOOST_CHECK_MESSAGE(p.get_state<my_machine_::State1&>().exit_counter == 2,"State1 exit not called correctly");
  150. BOOST_CHECK_MESSAGE(p.get_state<my_machine_::State1&>().entry_counter == 2,"State1 entry not called correctly");
  151. BOOST_CHECK_MESSAGE(p.get_state<my_machine_::State2&>().exit_counter == 2,"State2 exit not called correctly");
  152. BOOST_CHECK_MESSAGE(p.get_state<my_machine_::State2&>().entry_counter == 2,"State2 entry not called correctly");
  153. BOOST_CHECK_MESSAGE(p.get_state<my_machine_::State3&>().exit_counter == 2,"State3 exit not called correctly");
  154. BOOST_CHECK_MESSAGE(p.get_state<my_machine_::State3&>().entry_counter == 2,"State3 entry not called correctly");
  155. BOOST_CHECK_MESSAGE(p.get_state<my_machine_::State4&>().entry_counter == 2,"State4 entry not called correctly");
  156. BOOST_CHECK_MESSAGE(p.get_state<my_machine_::State4&>().exit_counter == 1,"State4 exit not called correctly");
  157. BOOST_CHECK_MESSAGE(p.always_true_counter == 2,"guard not called correctly");
  158. BOOST_CHECK_MESSAGE(p.always_false_counter == 2,"guard not called correctly");
  159. BOOST_CHECK_MESSAGE(p.state2_to_state3_counter == 2,"action not called correctly");
  160. BOOST_CHECK_MESSAGE(p.state3_to_state4_counter == 2,"action not called correctly");
  161. }
  162. }