AnonymousEuml.cpp 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  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. #include <boost/msm/front/euml/euml.hpp>
  14. #ifndef BOOST_MSM_NONSTANDALONE_TEST
  15. #define BOOST_TEST_MODULE MyTest
  16. #endif
  17. #include <boost/test/unit_test.hpp>
  18. namespace msm = boost::msm;
  19. using namespace boost::msm::front::euml;
  20. namespace
  21. {
  22. // events
  23. BOOST_MSM_EUML_EVENT(event1)
  24. // The list of FSM states
  25. BOOST_MSM_EUML_DECLARE_ATTRIBUTE(unsigned int,entry_counter)
  26. BOOST_MSM_EUML_DECLARE_ATTRIBUTE(unsigned int,exit_counter)
  27. BOOST_MSM_EUML_STATE(( ++state_(entry_counter),++state_(exit_counter),attributes_ << entry_counter << exit_counter),State1)
  28. BOOST_MSM_EUML_STATE(( ++state_(entry_counter),++state_(exit_counter),attributes_ << entry_counter << exit_counter),State2)
  29. BOOST_MSM_EUML_STATE(( ++state_(entry_counter),++state_(exit_counter),attributes_ << entry_counter << exit_counter),State3)
  30. BOOST_MSM_EUML_STATE(( ++state_(entry_counter),++state_(exit_counter),attributes_ << entry_counter << exit_counter),State4)
  31. BOOST_MSM_EUML_DECLARE_ATTRIBUTE(unsigned int,state2_to_state3_counter)
  32. BOOST_MSM_EUML_DECLARE_ATTRIBUTE(unsigned int,state3_to_state4_counter)
  33. BOOST_MSM_EUML_DECLARE_ATTRIBUTE(unsigned int,always_true_counter)
  34. BOOST_MSM_EUML_DECLARE_ATTRIBUTE(unsigned int,always_false_counter)
  35. // transition actions
  36. BOOST_MSM_EUML_ACTION(State2ToState3)
  37. {
  38. template <class FSM,class EVT,class SourceState,class TargetState>
  39. void operator()(EVT const& ,FSM& fsm,SourceState& ,TargetState& )
  40. {
  41. ++fsm.get_attribute(state2_to_state3_counter);
  42. }
  43. };
  44. BOOST_MSM_EUML_ACTION(State3ToState4)
  45. {
  46. template <class FSM,class EVT,class SourceState,class TargetState>
  47. void operator()(EVT const& ,FSM& fsm,SourceState& ,TargetState& )
  48. {
  49. ++fsm.get_attribute(state3_to_state4_counter);
  50. }
  51. };
  52. // guard conditions
  53. BOOST_MSM_EUML_ACTION(always_true)
  54. {
  55. template <class FSM,class EVT,class SourceState,class TargetState>
  56. bool operator()(EVT const&,FSM& fsm,SourceState& ,TargetState& )
  57. {
  58. ++fsm.get_attribute(always_true_counter);
  59. return true;
  60. }
  61. };
  62. BOOST_MSM_EUML_ACTION(always_false)
  63. {
  64. template <class FSM,class EVT,class SourceState,class TargetState>
  65. bool operator()(EVT const&,FSM& fsm,SourceState& ,TargetState& )
  66. {
  67. ++fsm.get_attribute(always_false_counter);
  68. return false;
  69. }
  70. };
  71. BOOST_MSM_EUML_ACTION(No_Transition)
  72. {
  73. template <class FSM,class Event>
  74. void operator()(Event const&,FSM&,int)
  75. {
  76. BOOST_FAIL("no_transition called!");
  77. }
  78. };
  79. BOOST_MSM_EUML_TRANSITION_TABLE((
  80. State2 == State1 ,
  81. State3 == State2 / State2ToState3,
  82. State4 == State3 [always_true] / State3ToState4,
  83. State4 == State3 [always_false],
  84. State1 == State4 + event1
  85. // +------------------------------------------------------------------------------+
  86. ),transition_table)
  87. // create a state machine "on the fly"
  88. BOOST_MSM_EUML_DECLARE_STATE_MACHINE(( transition_table, //STT
  89. init_ << State1, // Init State
  90. no_action, // Entry
  91. no_action, // Exit
  92. attributes_ << state2_to_state3_counter << state3_to_state4_counter
  93. << always_true_counter << always_false_counter, // Attributes
  94. configure_ << no_configure_, // configuration
  95. No_Transition // no_transition handler
  96. ),
  97. my_machine_) //fsm name
  98. // Pick a back-end
  99. typedef msm::back::state_machine<my_machine_> my_machine;
  100. //static char const* const state_names[] = { "State1", "State2", "State3", "State4" };
  101. BOOST_AUTO_TEST_CASE( my_test )
  102. {
  103. my_machine p;
  104. // needed to start the highest-level SM. This will call on_entry and mark the start of the SM
  105. // in this case it will also immediately trigger all anonymous transitions
  106. p.start();
  107. BOOST_CHECK_MESSAGE(p.current_state()[0] == 3,"State4 should be active"); //State4
  108. BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(State1)&>().get_attribute(exit_counter) == 1,
  109. "State1 exit not called correctly");
  110. BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(State1)&>().get_attribute(entry_counter) == 1,
  111. "State1 entry not called correctly");
  112. BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(State2)&>().get_attribute(exit_counter) == 1,
  113. "State2 exit not called correctly");
  114. BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(State2)&>().get_attribute(entry_counter) == 1,
  115. "State2 entry not called correctly");
  116. BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(State3)&>().get_attribute(exit_counter) == 1,
  117. "State3 exit not called correctly");
  118. BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(State3)&>().get_attribute(entry_counter) == 1,
  119. "State3 entry not called correctly");
  120. BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(State4)&>().get_attribute(entry_counter)== 1,
  121. "State4 entry not called correctly");
  122. BOOST_CHECK_MESSAGE(p.get_attribute(always_true_counter) == 1,"guard not called correctly");
  123. BOOST_CHECK_MESSAGE(p.get_attribute(always_false_counter) == 1,"guard not called correctly");
  124. BOOST_CHECK_MESSAGE(p.get_attribute(state2_to_state3_counter) == 1,"action not called correctly");
  125. BOOST_CHECK_MESSAGE(p.get_attribute(state3_to_state4_counter) == 1,"action not called correctly");
  126. // this event will bring us back to the initial state and thus, a new "loop" will be started
  127. p.process_event(event1);
  128. BOOST_CHECK_MESSAGE(p.current_state()[0] == 3,"State4 should be active"); //State4
  129. BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(State1)&>().get_attribute(exit_counter) == 2,
  130. "State1 exit not called correctly");
  131. BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(State1)&>().get_attribute(entry_counter) == 2,
  132. "State1 entry not called correctly");
  133. BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(State2)&>().get_attribute(exit_counter) == 2,
  134. "State2 exit not called correctly");
  135. BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(State2)&>().get_attribute(entry_counter) == 2,
  136. "State2 entry not called correctly");
  137. BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(State3)&>().get_attribute(exit_counter) == 2,
  138. "State3 exit not called correctly");
  139. BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(State3)&>().get_attribute(entry_counter) == 2,
  140. "State3 entry not called correctly");
  141. BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(State4)&>().get_attribute(entry_counter)== 2,
  142. "State4 entry not called correctly");
  143. BOOST_CHECK_MESSAGE(p.get_attribute(always_true_counter) == 2,"guard not called correctly");
  144. BOOST_CHECK_MESSAGE(p.get_attribute(always_false_counter) == 2,"guard not called correctly");
  145. BOOST_CHECK_MESSAGE(p.get_attribute(state2_to_state3_counter) == 2,"action not called correctly");
  146. BOOST_CHECK_MESSAGE(p.get_attribute(state3_to_state4_counter) == 2,"action not called correctly");
  147. }
  148. }