HistoryTest.cpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334
  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/simple_state.hpp>
  8. #include <boost/statechart/event.hpp>
  9. #include <boost/statechart/transition.hpp>
  10. #include <boost/statechart/shallow_history.hpp>
  11. #include <boost/statechart/deep_history.hpp>
  12. #include <boost/mpl/list.hpp>
  13. #include <boost/shared_ptr.hpp>
  14. #include <boost/test/test_tools.hpp>
  15. #include <stdexcept>
  16. namespace sc = boost::statechart;
  17. namespace mpl = boost::mpl;
  18. struct EvToB : sc::event< EvToB > {};
  19. struct EvToD : sc::event< EvToD > {};
  20. struct EvToDShallow : sc::event< EvToDShallow > {};
  21. struct EvToDDeep : sc::event< EvToDDeep > {};
  22. struct EvToDShallowLocal : sc::event< EvToDShallowLocal > {};
  23. struct EvToDDeepLocal : sc::event< EvToDDeepLocal > {};
  24. struct EvToF : sc::event< EvToF > {};
  25. struct EvToFShallow : sc::event< EvToFShallow > {};
  26. struct EvToFDeep : sc::event< EvToFDeep > {};
  27. struct EvToH : sc::event< EvToH > {};
  28. struct EvToI : sc::event< EvToI > {};
  29. struct EvToM : sc::event< EvToM > {};
  30. struct EvToQ : sc::event< EvToQ > {};
  31. struct EvWhatever : sc::event< EvWhatever > {};
  32. struct A;
  33. struct HistoryTest : sc::state_machine< HistoryTest, A >
  34. {
  35. void unconsumed_event( const sc::event_base & )
  36. {
  37. throw std::runtime_error( "Event was not consumed!" );
  38. }
  39. };
  40. struct B;
  41. struct D;
  42. struct F;
  43. struct H;
  44. struct I;
  45. struct M;
  46. struct Q;
  47. struct A : sc::simple_state< A, HistoryTest, B >
  48. {
  49. typedef mpl::list<
  50. sc::transition< EvToB, B >,
  51. sc::transition< EvToD, D >,
  52. sc::transition< EvToDShallow, sc::shallow_history< D > >,
  53. sc::transition< EvToDDeep, sc::deep_history< D > >,
  54. sc::transition< EvToF, F >,
  55. sc::transition< EvToFShallow, sc::shallow_history< F > >,
  56. sc::transition< EvToFDeep, sc::deep_history< F > >,
  57. sc::transition< EvToH, H >,
  58. sc::transition< EvToI, I >,
  59. sc::transition< EvToM, M >,
  60. sc::transition< EvToQ, Q >
  61. > reactions;
  62. };
  63. struct J;
  64. struct N;
  65. struct B : sc::simple_state<
  66. B, A, mpl::list< sc::shallow_history< J >, sc::deep_history< N > >,
  67. sc::has_full_history > {};
  68. struct J : sc::simple_state< J, B::orthogonal< 0 > > {};
  69. struct L;
  70. struct K : sc::simple_state< K, B::orthogonal< 0 >, L > {};
  71. struct L : sc::simple_state< L, K > {};
  72. struct M : sc::simple_state< M, K > {};
  73. struct N : sc::simple_state< N, B::orthogonal< 1 > > {};
  74. struct P;
  75. struct O : sc::simple_state< O, B::orthogonal< 1 >, P > {};
  76. struct P : sc::simple_state< P, O > {};
  77. struct Q : sc::simple_state< Q, O > {};
  78. struct C : sc::simple_state< C, A, D, sc::has_full_history > {};
  79. struct D : sc::simple_state< D, C > {};
  80. struct E : sc::simple_state< E, C, F, sc::has_full_history > {};
  81. struct F : sc::simple_state< F, E > {};
  82. struct G : sc::simple_state< G, E, H >
  83. {
  84. typedef mpl::list<
  85. sc::transition< EvToDShallowLocal, sc::shallow_history< D > >,
  86. sc::transition< EvToDDeepLocal, sc::deep_history< D > >
  87. > reactions;
  88. };
  89. struct H : sc::simple_state< H, G > {};
  90. struct I : sc::simple_state< I, G > {};
  91. int test_main( int, char* [] )
  92. {
  93. boost::shared_ptr< HistoryTest > pM =
  94. boost::shared_ptr< HistoryTest >( new HistoryTest() );
  95. // state_downcast sanity check
  96. BOOST_REQUIRE_THROW( pM->state_downcast< const B & >(), std::bad_cast );
  97. pM->initiate();
  98. BOOST_REQUIRE_THROW( pM->state_downcast< const D & >(), std::bad_cast );
  99. BOOST_REQUIRE_NO_THROW( pM->state_downcast< const B & >() );
  100. // No history has been saved yet -> default state
  101. pM->process_event( EvToDShallow() );
  102. BOOST_REQUIRE_NO_THROW( pM->state_downcast< const D & >() );
  103. pM->process_event( EvToDShallow() );
  104. BOOST_REQUIRE_NO_THROW( pM->state_downcast< const D & >() );
  105. pM->process_event( EvToI() );
  106. BOOST_REQUIRE_NO_THROW( pM->state_downcast< const I & >() );
  107. // Direct inner is E when history is saved -> F
  108. pM->process_event( EvToDShallow() );
  109. BOOST_REQUIRE_NO_THROW( pM->state_downcast< const F & >() );
  110. pM->process_event( EvToH() );
  111. BOOST_REQUIRE_NO_THROW( pM->state_downcast< const H & >() );
  112. // Direct inner is E when history is saved -> F
  113. pM->process_event( EvToDShallow() );
  114. BOOST_REQUIRE_NO_THROW( pM->state_downcast< const F & >() );
  115. pM->process_event( EvToF() );
  116. BOOST_REQUIRE_NO_THROW( pM->state_downcast< const F & >() );
  117. pM->process_event( EvToB() );
  118. BOOST_REQUIRE_NO_THROW( pM->state_downcast< const B & >() );
  119. // Direct inner was E when history was saved -> F
  120. pM->process_event( EvToDShallow() );
  121. BOOST_REQUIRE_NO_THROW( pM->state_downcast< const F & >() );
  122. pM->initiate();
  123. // History was cleared in termination -> default state
  124. pM->process_event( EvToDShallow() );
  125. BOOST_REQUIRE_NO_THROW( pM->state_downcast< const D & >() );
  126. pM->process_event( EvToI() );
  127. BOOST_REQUIRE_NO_THROW( pM->state_downcast< const I & >() );
  128. pM->process_event( EvToB() );
  129. BOOST_REQUIRE_NO_THROW( pM->state_downcast< const B & >() );
  130. pM->clear_shallow_history< C, 0 >();
  131. // History was cleared -> default state
  132. pM->process_event( EvToDShallow() );
  133. BOOST_REQUIRE_NO_THROW( pM->state_downcast< const D & >() );
  134. pM = boost::shared_ptr< HistoryTest >( new HistoryTest() );
  135. pM->initiate();
  136. BOOST_REQUIRE_NO_THROW( pM->state_downcast< const B & >() );
  137. // No history has been saved yet -> default state
  138. pM->process_event( EvToDDeep() );
  139. BOOST_REQUIRE_NO_THROW( pM->state_downcast< const D & >() );
  140. pM->process_event( EvToDDeep() );
  141. BOOST_REQUIRE_NO_THROW( pM->state_downcast< const D & >() );
  142. pM->process_event( EvToI() );
  143. BOOST_REQUIRE_NO_THROW( pM->state_downcast< const I & >() );
  144. pM->process_event( EvToB() );
  145. BOOST_REQUIRE_NO_THROW( pM->state_downcast< const B & >() );
  146. pM->process_event( EvToDDeep() );
  147. BOOST_REQUIRE_NO_THROW( pM->state_downcast< const I & >() );
  148. pM->process_event( EvToH() );
  149. BOOST_REQUIRE_NO_THROW( pM->state_downcast< const H & >() );
  150. pM->process_event( EvToB() );
  151. BOOST_REQUIRE_NO_THROW( pM->state_downcast< const B & >() );
  152. pM->process_event( EvToDDeep() );
  153. BOOST_REQUIRE_NO_THROW( pM->state_downcast< const H & >() );
  154. pM->process_event( EvToF() );
  155. BOOST_REQUIRE_NO_THROW( pM->state_downcast< const F & >() );
  156. pM->process_event( EvToB() );
  157. BOOST_REQUIRE_NO_THROW( pM->state_downcast< const B & >() );
  158. pM->process_event( EvToDDeep() );
  159. BOOST_REQUIRE_NO_THROW( pM->state_downcast< const F & >() );
  160. pM->initiate();
  161. // History was cleared in termination -> default state
  162. pM->process_event( EvToDDeep() );
  163. BOOST_REQUIRE_NO_THROW( pM->state_downcast< const D & >() );
  164. pM->process_event( EvToI() );
  165. BOOST_REQUIRE_NO_THROW( pM->state_downcast< const I & >() );
  166. pM->process_event( EvToB() );
  167. BOOST_REQUIRE_NO_THROW( pM->state_downcast< const B & >() );
  168. pM->clear_deep_history< C, 0 >();
  169. // History was cleared -> default state
  170. pM->process_event( EvToDDeep() );
  171. BOOST_REQUIRE_NO_THROW( pM->state_downcast< const D & >() );
  172. pM = boost::shared_ptr< HistoryTest >( new HistoryTest() );
  173. pM->initiate();
  174. BOOST_REQUIRE_NO_THROW( pM->state_downcast< const B & >() );
  175. // No history has been saved yet -> default state
  176. pM->process_event( EvToFShallow() );
  177. BOOST_REQUIRE_NO_THROW( pM->state_downcast< const F & >() );
  178. pM->process_event( EvToFShallow() );
  179. BOOST_REQUIRE_NO_THROW( pM->state_downcast< const F & >() );
  180. pM->process_event( EvToI() );
  181. BOOST_REQUIRE_NO_THROW( pM->state_downcast< const I & >() );
  182. // Direct inner is G when history is saved -> H
  183. pM->process_event( EvToFShallow() );
  184. BOOST_REQUIRE_NO_THROW( pM->state_downcast< const H & >() );
  185. pM->process_event( EvToH() );
  186. BOOST_REQUIRE_NO_THROW( pM->state_downcast< const H & >() );
  187. pM->process_event( EvToB() );
  188. BOOST_REQUIRE_NO_THROW( pM->state_downcast< const B & >() );
  189. // Direct inner was G when history was saved -> H
  190. pM->process_event( EvToFShallow() );
  191. BOOST_REQUIRE_NO_THROW( pM->state_downcast< const H & >() );
  192. pM->process_event( EvToI() );
  193. BOOST_REQUIRE_NO_THROW( pM->state_downcast< const I & >() );
  194. pM->initiate();
  195. // History was cleared in termination -> default state
  196. pM->process_event( EvToFShallow() );
  197. BOOST_REQUIRE_NO_THROW( pM->state_downcast< const F & >() );
  198. pM->process_event( EvToI() );
  199. BOOST_REQUIRE_NO_THROW( pM->state_downcast< const I & >() );
  200. pM->process_event( EvToB() );
  201. BOOST_REQUIRE_NO_THROW( pM->state_downcast< const B & >() );
  202. pM->clear_shallow_history< E, 0 >();
  203. // History was cleared -> default state
  204. pM->process_event( EvToFShallow() );
  205. BOOST_REQUIRE_NO_THROW( pM->state_downcast< const F & >() );
  206. pM = boost::shared_ptr< HistoryTest >( new HistoryTest() );
  207. pM->initiate();
  208. BOOST_REQUIRE_NO_THROW( pM->state_downcast< const B & >() );
  209. // No history has been saved yet -> default state
  210. pM->process_event( EvToFDeep() );
  211. BOOST_REQUIRE_NO_THROW( pM->state_downcast< const F & >() );
  212. pM->process_event( EvToFDeep() );
  213. BOOST_REQUIRE_NO_THROW( pM->state_downcast< const F & >() );
  214. pM->process_event( EvToI() );
  215. BOOST_REQUIRE_NO_THROW( pM->state_downcast< const I & >() );
  216. pM->process_event( EvToB() );
  217. BOOST_REQUIRE_NO_THROW( pM->state_downcast< const B & >() );
  218. pM->process_event( EvToFDeep() );
  219. BOOST_REQUIRE_NO_THROW( pM->state_downcast< const I & >() );
  220. pM->process_event( EvToH() );
  221. BOOST_REQUIRE_NO_THROW( pM->state_downcast< const H & >() );
  222. pM->process_event( EvToB() );
  223. BOOST_REQUIRE_NO_THROW( pM->state_downcast< const B & >() );
  224. pM->process_event( EvToFDeep() );
  225. BOOST_REQUIRE_NO_THROW( pM->state_downcast< const H & >() );
  226. pM->process_event( EvToF() );
  227. BOOST_REQUIRE_NO_THROW( pM->state_downcast< const F & >() );
  228. pM->process_event( EvToB() );
  229. BOOST_REQUIRE_NO_THROW( pM->state_downcast< const B & >() );
  230. pM->process_event( EvToFDeep() );
  231. BOOST_REQUIRE_NO_THROW( pM->state_downcast< const F & >() );
  232. pM->initiate();
  233. // History was cleared in termination -> default state
  234. pM->process_event( EvToFDeep() );
  235. BOOST_REQUIRE_NO_THROW( pM->state_downcast< const F & >() );
  236. pM->process_event( EvToI() );
  237. BOOST_REQUIRE_NO_THROW( pM->state_downcast< const I & >() );
  238. pM->process_event( EvToB() );
  239. BOOST_REQUIRE_NO_THROW( pM->state_downcast< const B & >() );
  240. pM->clear_deep_history< E, 0 >();
  241. // History was cleared -> default state
  242. pM->process_event( EvToFDeep() );
  243. BOOST_REQUIRE_NO_THROW( pM->state_downcast< const F & >() );
  244. // Test local history (new with UML 2.0)
  245. pM->initiate();
  246. // unconsumed_event sanity check
  247. BOOST_REQUIRE_THROW( pM->process_event( EvWhatever() ), std::runtime_error );
  248. pM->process_event( EvToI() );
  249. BOOST_REQUIRE_NO_THROW( pM->state_downcast< const I & >() );
  250. pM->process_event( EvToDShallowLocal() );
  251. BOOST_REQUIRE_NO_THROW( pM->state_downcast< const F & >() );
  252. pM->process_event( EvToI() );
  253. pM->process_event( EvToDDeepLocal() );
  254. BOOST_REQUIRE_NO_THROW( pM->state_downcast< const I & >() );
  255. // Given that history transitions and history initial states are implemented
  256. // with the same code we just make a few sanity checks and trust that the
  257. // rest will work just like we tested above.
  258. pM->process_event( EvToB() );
  259. BOOST_REQUIRE_NO_THROW( pM->state_downcast< const J & >() );
  260. BOOST_REQUIRE_NO_THROW( pM->state_downcast< const N & >() );
  261. pM->process_event( EvToM() );
  262. BOOST_REQUIRE_NO_THROW( pM->state_downcast< const M & >() );
  263. // Direct inner is K when history is saved -> L
  264. pM->process_event( EvToB() );
  265. BOOST_REQUIRE_NO_THROW( pM->state_downcast< const L & >() );
  266. BOOST_REQUIRE_NO_THROW( pM->state_downcast< const N & >() );
  267. pM->process_event( EvToQ() );
  268. BOOST_REQUIRE_NO_THROW( pM->state_downcast< const Q & >() );
  269. pM->process_event( EvToB() );
  270. BOOST_REQUIRE_NO_THROW( pM->state_downcast< const Q & >() );
  271. return 0;
  272. }