TestDeferAndMessageQueue.cpp 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194
  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/functor_row.hpp>
  16. #include <boost/test/unit_test.hpp>
  17. namespace msm = boost::msm;
  18. namespace mpl = boost::mpl;
  19. using namespace boost::msm::front;
  20. namespace
  21. {
  22. // events
  23. struct eventResolve {};
  24. struct eventConnect {};
  25. struct eventResolved {};
  26. struct eventRead {};
  27. struct eventd {};
  28. // front-end: define the FSM structure
  29. struct player_ : public msm::front::state_machine_def<player_>
  30. {
  31. player_()
  32. :expected_action_counter(0)
  33. {}
  34. struct enqueue_action1
  35. {
  36. template <class EVT,class FSM,class SourceState,class TargetState>
  37. void operator()(EVT const& ,FSM& fsm,SourceState& ,TargetState& )
  38. {
  39. fsm.template process_event(eventResolve());
  40. }
  41. };
  42. struct enqueue_action2
  43. {
  44. template <class EVT,class FSM,class SourceState,class TargetState>
  45. void operator()(EVT const& ,FSM& fsm,SourceState& ,TargetState& )
  46. {
  47. fsm.template process_event(eventConnect());
  48. }
  49. };
  50. struct expected_action
  51. {
  52. template <class EVT,class FSM,class SourceState,class TargetState>
  53. void operator()(EVT const& ,FSM& fsm,SourceState& ,TargetState& )
  54. {
  55. ++fsm.expected_action_counter;
  56. //std::cout << "expected action called" << std::endl;
  57. }
  58. };
  59. struct unexpected_action
  60. {
  61. template <class EVT,class FSM,class SourceState,class TargetState>
  62. void operator()(EVT const& ,FSM& fsm,SourceState& ,TargetState& )
  63. {
  64. std::cout << "unexpected action called" << std::endl;
  65. }
  66. };
  67. // The list of FSM states
  68. struct Unresolved : public msm::front::state<>
  69. {
  70. typedef mpl::vector<eventRead > deferred_events;
  71. template <class Event,class FSM>
  72. void on_entry(Event const&,FSM& ) {++entry_counter;}
  73. template <class Event,class FSM>
  74. void on_exit(Event const&,FSM& ) {++exit_counter;}
  75. int entry_counter;
  76. int exit_counter;
  77. // Transition table for Empty
  78. struct internal_transition_table : mpl::vector<
  79. // Start Event Next Action Guard
  80. Internal < eventConnect , msm::front::ActionSequence_<mpl::vector<enqueue_action1,enqueue_action2>> >
  81. // +---------+-------------+---------+---------------------+----------------------+
  82. > {};
  83. };
  84. struct Resolving : public msm::front::state<>
  85. {
  86. typedef mpl::vector<eventConnect > deferred_events;
  87. template <class Event,class FSM>
  88. void on_entry(Event const&,FSM& ) {++entry_counter;}
  89. template <class Event,class FSM>
  90. void on_exit(Event const&,FSM& ) {++exit_counter;}
  91. int entry_counter;
  92. int exit_counter;
  93. };
  94. struct Resolved : public msm::front::state<>
  95. {
  96. template <class Event,class FSM>
  97. void on_entry(Event const&,FSM& ) {++entry_counter;}
  98. template <class Event,class FSM>
  99. void on_exit(Event const&,FSM& ) {++exit_counter;}
  100. int entry_counter;
  101. int exit_counter;
  102. };
  103. struct Connecting : public msm::front::state<>
  104. {
  105. template <class Event,class FSM>
  106. void on_entry(Event const&,FSM& ) {++entry_counter;}
  107. template <class Event,class FSM>
  108. void on_exit(Event const&,FSM& ) {++exit_counter;}
  109. int entry_counter;
  110. int exit_counter;
  111. };
  112. struct State22 : public msm::front::state<>
  113. {
  114. template <class Event,class FSM>
  115. void on_entry(Event const&,FSM& ) {++entry_counter;}
  116. template <class Event,class FSM>
  117. void on_exit(Event const&,FSM& ) {++exit_counter;}
  118. int entry_counter;
  119. int exit_counter;
  120. };
  121. // the initial state of the player SM. Must be defined
  122. typedef mpl::vector<Unresolved,State22> initial_state;
  123. // Transition table for player
  124. struct transition_table : mpl::vector<
  125. // Start Event Next Action Guard
  126. // +---------+-------------+---------+---------------------+----------------------+
  127. Row < Unresolved , eventResolve , Resolving >,
  128. Row < Resolving , eventResolved , Resolved >,
  129. Row < Resolved , eventConnect , Connecting , expected_action >,
  130. Row < State22 , eventd , State22 >
  131. // +---------+-------------+---------+---------------------+----------------------+
  132. > {};
  133. // Replaces the default no-transition response.
  134. template <class FSM,class Event>
  135. void no_transition(Event const& , FSM&,int )
  136. {
  137. BOOST_FAIL("no_transition called!");
  138. }
  139. // init counters
  140. template <class Event,class FSM>
  141. void on_entry(Event const&,FSM& fsm)
  142. {
  143. fsm.template get_state<player_::Unresolved&>().entry_counter=0;
  144. fsm.template get_state<player_::Unresolved&>().exit_counter=0;
  145. fsm.template get_state<player_::Resolving&>().entry_counter=0;
  146. fsm.template get_state<player_::Resolving&>().exit_counter=0;
  147. fsm.template get_state<player_::Resolved&>().entry_counter=0;
  148. fsm.template get_state<player_::Resolved&>().exit_counter=0;
  149. fsm.template get_state<player_::Connecting&>().entry_counter=0;
  150. fsm.template get_state<player_::Connecting&>().exit_counter=0;
  151. }
  152. int expected_action_counter;
  153. };
  154. // Pick a back-end
  155. typedef msm::back::state_machine<player_> player;
  156. BOOST_AUTO_TEST_CASE( TestDeferAndMessageQueue )
  157. {
  158. player p;
  159. // needed to start the highest-level SM. This will call on_entry and mark the start of the SM
  160. p.start();
  161. p.process_event(eventConnect());
  162. BOOST_CHECK_MESSAGE(p.current_state()[0] == 1,"Resolving should be active");
  163. BOOST_CHECK_MESSAGE(p.current_state()[1] == 3,"State22 should be active");
  164. BOOST_CHECK_MESSAGE(p.get_state<player_::Unresolved&>().exit_counter == 1,"Unresolved exit not called correctly");
  165. BOOST_CHECK_MESSAGE(p.get_state<player_::Unresolved&>().entry_counter == 1,"Unresolved entry not called correctly");
  166. BOOST_CHECK_MESSAGE(p.get_state<player_::Resolving&>().entry_counter == 1,"Resolving entry not called correctly");
  167. p.process_event(eventResolved());
  168. BOOST_CHECK_MESSAGE(p.current_state()[0] == 4,"Connecting should be active");
  169. BOOST_CHECK_MESSAGE(p.current_state()[1] == 3,"State22 should be active");
  170. BOOST_CHECK_MESSAGE(p.get_state<player_::Resolved&>().exit_counter == 1,"Resolved exit not called correctly");
  171. BOOST_CHECK_MESSAGE(p.get_state<player_::Resolved&>().entry_counter == 1,"Resolved entry not called correctly");
  172. BOOST_CHECK_MESSAGE(p.get_state<player_::Resolving&>().exit_counter == 1,"Resolving exit not called correctly");
  173. BOOST_CHECK_MESSAGE(p.get_state<player_::Connecting&>().entry_counter == 1,"Connecting entry not called correctly");
  174. BOOST_CHECK_MESSAGE(p.expected_action_counter == 1,"expected_action should have been called");
  175. }
  176. }