TerminationTest.cpp 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283
  1. //////////////////////////////////////////////////////////////////////////////
  2. // Copyright 2005-2006 Andreas Huber Doenni
  3. // Distributed under the Boost Software License, Version 1.0. (See accompany-
  4. // ing file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  5. //////////////////////////////////////////////////////////////////////////////
  6. #include <boost/statechart/state_machine.hpp>
  7. #include <boost/statechart/event.hpp>
  8. #include <boost/statechart/simple_state.hpp>
  9. #include <boost/statechart/termination.hpp>
  10. #include <boost/mpl/list.hpp>
  11. #include <boost/test/test_tools.hpp>
  12. #include <set>
  13. #include <map>
  14. #include <string>
  15. namespace sc = boost::statechart;
  16. namespace mpl = boost::mpl;
  17. struct EvTerminateA : sc::event< EvTerminateA > {};
  18. struct EvTerminateB : sc::event< EvTerminateB > {};
  19. struct EvTerminateC : sc::event< EvTerminateC > {};
  20. struct EvTerminateD : sc::event< EvTerminateD > {};
  21. struct EvTerminateE : sc::event< EvTerminateE > {};
  22. struct EvTerminateF : sc::event< EvTerminateF > {};
  23. struct EvTerminateG : sc::event< EvTerminateG > {};
  24. struct A;
  25. struct TerminationTest : sc::state_machine< TerminationTest, A >
  26. {
  27. public:
  28. //////////////////////////////////////////////////////////////////////////
  29. TerminationTest();
  30. void AssertInState( const std::string & stateNames ) const
  31. {
  32. stateNamesCache_.clear();
  33. for ( state_iterator currentState = state_begin();
  34. currentState != state_end(); ++currentState )
  35. {
  36. AddName( currentState->dynamic_type() );
  37. const state_base_type * outerState = currentState->outer_state_ptr();
  38. while ( outerState != 0 )
  39. {
  40. AddName( outerState->dynamic_type() );
  41. outerState = outerState->outer_state_ptr();
  42. }
  43. }
  44. std::string::const_iterator expectedName = stateNames.begin();
  45. BOOST_REQUIRE( stateNames.size() == stateNamesCache_.size() );
  46. for ( StateNamesCache::const_iterator actualName =
  47. stateNamesCache_.begin(); actualName != stateNamesCache_.end();
  48. ++actualName, ++expectedName )
  49. {
  50. BOOST_REQUIRE( ( *actualName )[ 0 ] == *expectedName );
  51. }
  52. }
  53. private:
  54. //////////////////////////////////////////////////////////////////////////
  55. void AddName( state_base_type::id_type stateType ) const
  56. {
  57. const StateNamesMap::const_iterator found =
  58. stateNamesMap_.find( stateType );
  59. BOOST_REQUIRE( found != stateNamesMap_.end() );
  60. stateNamesCache_.insert( found->second );
  61. }
  62. typedef std::map< state_base_type::id_type, std::string > StateNamesMap;
  63. typedef std::set< std::string > StateNamesCache;
  64. StateNamesMap stateNamesMap_;
  65. mutable StateNamesCache stateNamesCache_;
  66. };
  67. template<
  68. class MostDerived,
  69. class Context,
  70. class InnerInitial = mpl::list<> >
  71. struct MyState : sc::simple_state< MostDerived, Context, InnerInitial >
  72. {
  73. public:
  74. MyState() : exitCalled_( false ) {}
  75. ~MyState()
  76. {
  77. // BOOST_REQUIRE throws an exception when the test fails. If the state
  78. // is destructed as part of a stack unwind, abort() is called what is
  79. // presumably also detected by the test monitor.
  80. BOOST_REQUIRE( exitCalled_ );
  81. }
  82. void exit()
  83. {
  84. exitCalled_ = true;
  85. }
  86. private:
  87. bool exitCalled_;
  88. };
  89. struct B;
  90. struct C;
  91. struct A : MyState< A, TerminationTest, mpl::list< B, C > >
  92. {
  93. typedef sc::termination< EvTerminateA > reactions;
  94. };
  95. struct B : MyState< B, A::orthogonal< 0 > >
  96. {
  97. typedef sc::termination< EvTerminateB > reactions;
  98. };
  99. struct D;
  100. struct E;
  101. struct C : MyState< C, A::orthogonal< 1 >, mpl::list< D, E > >
  102. {
  103. typedef sc::termination< EvTerminateC > reactions;
  104. };
  105. struct D : MyState< D, C::orthogonal< 0 > >
  106. {
  107. typedef sc::termination< EvTerminateD > reactions;
  108. };
  109. struct F;
  110. struct G;
  111. struct E : MyState< E, C::orthogonal< 1 >, mpl::list< F, G > >
  112. {
  113. typedef sc::termination< EvTerminateE > reactions;
  114. };
  115. struct F : MyState< F, E::orthogonal< 0 > >
  116. {
  117. typedef sc::termination< EvTerminateF > reactions;
  118. };
  119. struct G : MyState< G, E::orthogonal< 1 > >
  120. {
  121. typedef sc::termination< EvTerminateG > reactions;
  122. };
  123. TerminationTest::TerminationTest()
  124. {
  125. // We're not using custom type information to make this test work even when
  126. // BOOST_STATECHART_USE_NATIVE_RTTI is defined
  127. stateNamesMap_[ A::static_type() ] = "A";
  128. stateNamesMap_[ B::static_type() ] = "B";
  129. stateNamesMap_[ C::static_type() ] = "C";
  130. stateNamesMap_[ D::static_type() ] = "D";
  131. stateNamesMap_[ E::static_type() ] = "E";
  132. stateNamesMap_[ F::static_type() ] = "F";
  133. stateNamesMap_[ G::static_type() ] = "G";
  134. }
  135. struct X;
  136. struct TerminationEventBaseTest :
  137. sc::state_machine< TerminationEventBaseTest, X > {};
  138. struct X : sc::simple_state< X, TerminationEventBaseTest >
  139. {
  140. typedef sc::termination< sc::event_base > reactions;
  141. };
  142. int test_main( int, char* [] )
  143. {
  144. TerminationTest machine;
  145. machine.AssertInState( "" );
  146. machine.initiate();
  147. machine.AssertInState( "ABCDEFG" );
  148. machine.process_event( EvTerminateE() );
  149. machine.AssertInState( "ABCD" );
  150. machine.process_event( EvTerminateE() );
  151. machine.AssertInState( "ABCD" );
  152. machine.initiate();
  153. machine.AssertInState( "ABCDEFG" );
  154. machine.process_event( EvTerminateC() );
  155. machine.AssertInState( "AB" );
  156. machine.process_event( EvTerminateC() );
  157. machine.AssertInState( "AB" );
  158. machine.initiate();
  159. machine.AssertInState( "ABCDEFG" );
  160. machine.process_event( EvTerminateA() );
  161. machine.AssertInState( "" );
  162. machine.process_event( EvTerminateA() );
  163. machine.AssertInState( "" );
  164. machine.initiate();
  165. machine.AssertInState( "ABCDEFG" );
  166. machine.process_event( EvTerminateG() );
  167. machine.AssertInState( "ABCDEF" );
  168. machine.process_event( EvTerminateG() );
  169. machine.AssertInState( "ABCDEF" );
  170. machine.process_event( EvTerminateF() );
  171. machine.AssertInState( "ABCD" );
  172. machine.process_event( EvTerminateF() );
  173. machine.AssertInState( "ABCD" );
  174. machine.process_event( EvTerminateD() );
  175. machine.AssertInState( "AB" );
  176. machine.process_event( EvTerminateD() );
  177. machine.AssertInState( "AB" );
  178. machine.process_event( EvTerminateB() );
  179. machine.AssertInState( "" );
  180. machine.process_event( EvTerminateB() );
  181. machine.AssertInState( "" );
  182. machine.initiate();
  183. machine.AssertInState( "ABCDEFG" );
  184. machine.process_event( EvTerminateB() );
  185. machine.AssertInState( "ACDEFG" );
  186. machine.process_event( EvTerminateB() );
  187. machine.AssertInState( "ACDEFG" );
  188. machine.process_event( EvTerminateD() );
  189. machine.AssertInState( "ACEFG" );
  190. machine.process_event( EvTerminateD() );
  191. machine.AssertInState( "ACEFG" );
  192. machine.process_event( EvTerminateF() );
  193. machine.AssertInState( "ACEG" );
  194. machine.process_event( EvTerminateF() );
  195. machine.AssertInState( "ACEG" );
  196. machine.process_event( EvTerminateG() );
  197. machine.AssertInState( "" );
  198. machine.process_event( EvTerminateG() );
  199. machine.AssertInState( "" );
  200. machine.initiate();
  201. machine.AssertInState( "ABCDEFG" );
  202. machine.process_event( EvTerminateE() );
  203. machine.AssertInState( "ABCD" );
  204. machine.process_event( EvTerminateE() );
  205. machine.AssertInState( "ABCD" );
  206. machine.process_event( EvTerminateC() );
  207. machine.AssertInState( "AB" );
  208. machine.process_event( EvTerminateC() );
  209. machine.AssertInState( "AB" );
  210. machine.process_event( EvTerminateA() );
  211. machine.AssertInState( "" );
  212. machine.process_event( EvTerminateA() );
  213. machine.AssertInState( "" );
  214. machine.initiate();
  215. machine.AssertInState( "ABCDEFG" );
  216. machine.initiate();
  217. machine.AssertInState( "ABCDEFG" );
  218. machine.terminate();
  219. machine.AssertInState( "" );
  220. machine.terminate();
  221. machine.AssertInState( "" );
  222. TerminationEventBaseTest eventBaseMachine;
  223. eventBaseMachine.initiate();
  224. BOOST_REQUIRE( !eventBaseMachine.terminated() );
  225. eventBaseMachine.process_event( EvTerminateA() );
  226. BOOST_REQUIRE( eventBaseMachine.terminated() );
  227. eventBaseMachine.initiate();
  228. BOOST_REQUIRE( !eventBaseMachine.terminated() );
  229. eventBaseMachine.process_event( EvTerminateB() );
  230. BOOST_REQUIRE( eventBaseMachine.terminated() );
  231. return 0;
  232. }