TransitionTest.cpp 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849
  1. //////////////////////////////////////////////////////////////////////////////
  2. // Copyright 2004-2007 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 "OuterOrthogonal.hpp"
  7. #include "InnermostDefault.hpp"
  8. #include <boost/statechart/state_machine.hpp>
  9. #include <boost/statechart/null_exception_translator.hpp>
  10. #include <boost/statechart/exception_translator.hpp>
  11. #include <boost/statechart/event.hpp>
  12. #include <boost/statechart/transition.hpp>
  13. #include <boost/statechart/custom_reaction.hpp>
  14. #include <boost/mpl/list.hpp>
  15. #include <boost/test/test_tools.hpp>
  16. #include <typeinfo>
  17. #include <string>
  18. #include <vector>
  19. #include <iostream>
  20. #include <algorithm>
  21. #include <stdexcept>
  22. namespace sc = boost::statechart;
  23. namespace mpl = boost::mpl;
  24. typedef std::string ActionDescription();
  25. typedef ActionDescription * ActionDescriptionPtr;
  26. typedef std::vector< ActionDescriptionPtr > ActionDescriptionSequence;
  27. typedef ActionDescriptionSequence::const_iterator SequenceIterator;
  28. typedef void Action( ActionDescriptionSequence & );
  29. typedef Action * ActionPtr;
  30. template< class State >
  31. std::string EntryDescription()
  32. {
  33. static const std::string entry = "Entry: ";
  34. return entry + typeid( State ).name() + "\n";
  35. }
  36. template< class State >
  37. std::string ExitFnDescription()
  38. {
  39. static const std::string exitFunction = "exit(): ";
  40. return exitFunction + typeid( State ).name() + "\n";
  41. }
  42. template< class State >
  43. std::string DtorDescription()
  44. {
  45. static const std::string destructor = "Destructor: ";
  46. return destructor + typeid( State ).name() + "\n";
  47. }
  48. template< class Context, class Event >
  49. std::string TransDescription()
  50. {
  51. static const std::string transition = "Transition: ";
  52. static const std::string event = " with Event: ";
  53. return transition + typeid( Context ).name() +
  54. event + typeid( Event ).name() + "\n";
  55. }
  56. template< ActionPtr pAction >
  57. std::string ThrowDescription()
  58. {
  59. static const std::string throwing = "Throwing exception in ";
  60. ActionDescriptionSequence sequence;
  61. pAction( sequence );
  62. return throwing + sequence.front()();
  63. }
  64. template< class State >
  65. void Entry( ActionDescriptionSequence & sequence )
  66. {
  67. sequence.push_back( &EntryDescription< State > );
  68. }
  69. template< class State >
  70. void ExitFn( ActionDescriptionSequence & sequence )
  71. {
  72. sequence.push_back( &ExitFnDescription< State > );
  73. }
  74. template< class State >
  75. void Dtor( ActionDescriptionSequence & sequence )
  76. {
  77. sequence.push_back( &DtorDescription< State > );
  78. }
  79. template< class State >
  80. void Exit( ActionDescriptionSequence & sequence )
  81. {
  82. ExitFn< State >( sequence );
  83. Dtor< State >( sequence );
  84. }
  85. template< class Context, class Event >
  86. void Trans( ActionDescriptionSequence & sequence )
  87. {
  88. sequence.push_back( &TransDescription< Context, Event > );
  89. }
  90. template< ActionPtr pAction >
  91. void Throw( ActionDescriptionSequence & sequence )
  92. {
  93. sequence.push_back( &ThrowDescription< pAction > );
  94. }
  95. const int arrayLength = 30;
  96. typedef ActionPtr ActionArray[ arrayLength ];
  97. class TransitionTestException : public std::runtime_error
  98. {
  99. public:
  100. TransitionTestException() : std::runtime_error( "Oh la la!" ) {}
  101. };
  102. // This test state machine is a beefed-up version of the one presented in
  103. // "Practical Statecharts in C/C++" by Miro Samek, CMP Books 2002
  104. struct A : sc::event< A > {};
  105. struct B : sc::event< B > {};
  106. struct C : sc::event< C > {};
  107. struct D : sc::event< D > {};
  108. struct E : sc::event< E > {};
  109. struct F : sc::event< F > {};
  110. struct G : sc::event< G > {};
  111. struct H : sc::event< H > {};
  112. template< class M > struct S0;
  113. template< class Translator >
  114. struct TransitionTest : sc::state_machine<
  115. TransitionTest< Translator >, S0< TransitionTest< Translator > >,
  116. std::allocator< sc::none >, Translator >
  117. {
  118. public:
  119. //////////////////////////////////////////////////////////////////////////
  120. TransitionTest() : pThrowAction_( 0 ), unconsumedEventCount_( 0 ) {}
  121. ~TransitionTest()
  122. {
  123. // Since state destructors access the state machine object, we need to
  124. // make sure that all states are destructed before this subtype
  125. // portion is destructed.
  126. this->terminate();
  127. }
  128. void CompareToExpectedActionSequence( ActionArray & actions )
  129. {
  130. expectedSequence_.clear();
  131. // Copy all non-null pointers in actions into expectedSequence_
  132. for ( ActionPtr * pCurrent = &actions[ 0 ];
  133. ( pCurrent != &actions[ arrayLength ] ) && ( *pCurrent != 0 );
  134. ++pCurrent )
  135. {
  136. ( *pCurrent )( expectedSequence_ );
  137. }
  138. if ( ( expectedSequence_.size() != actualSequence_.size() ) ||
  139. !std::equal( expectedSequence_.begin(),
  140. expectedSequence_.end(), actualSequence_.begin() ) )
  141. {
  142. std::string message = "\nExpected action sequence:\n";
  143. for ( SequenceIterator pExpected = expectedSequence_.begin();
  144. pExpected != expectedSequence_.end(); ++pExpected )
  145. {
  146. message += ( *pExpected )();
  147. }
  148. message += "\nActual action sequence:\n";
  149. for ( SequenceIterator pActual = actualSequence_.begin();
  150. pActual != actualSequence_.end(); ++pActual )
  151. {
  152. message += ( *pActual )();
  153. }
  154. BOOST_FAIL( message.c_str() );
  155. }
  156. actualSequence_.clear();
  157. }
  158. void ClearActualSequence()
  159. {
  160. actualSequence_.clear();
  161. }
  162. void ThrowAction( ActionPtr pThrowAction )
  163. {
  164. pThrowAction_ = pThrowAction;
  165. }
  166. template< class State >
  167. void ActualEntry()
  168. {
  169. StoreActualAction< &Entry< State > >();
  170. }
  171. template< class State >
  172. void ActualExitFunction()
  173. {
  174. StoreActualAction< &ExitFn< State > >();
  175. }
  176. template< class State >
  177. void ActualDestructor()
  178. {
  179. StoreActualAction< &Dtor< State > >();
  180. }
  181. template< class Context, class Event >
  182. void ActualTransition()
  183. {
  184. StoreActualAction< &Trans< Context, Event > >();
  185. }
  186. void unconsumed_event( const sc::event_base & )
  187. {
  188. ++unconsumedEventCount_;
  189. }
  190. unsigned int GetUnconsumedEventCount() const
  191. {
  192. return unconsumedEventCount_;
  193. }
  194. private:
  195. //////////////////////////////////////////////////////////////////////////
  196. template< ActionPtr pAction >
  197. void StoreActualAction()
  198. {
  199. if ( pAction == pThrowAction_ )
  200. {
  201. Throw< pAction >( actualSequence_ );
  202. throw TransitionTestException();
  203. }
  204. else
  205. {
  206. pAction( actualSequence_ );
  207. }
  208. }
  209. ActionPtr pThrowAction_;
  210. ActionDescriptionSequence actualSequence_;
  211. ActionDescriptionSequence expectedSequence_;
  212. unsigned int unconsumedEventCount_;
  213. };
  214. template< class M > struct S1;
  215. template< class M > struct S211;
  216. template< class M >
  217. struct S0 : Orthogonal0< S0< M >, M, S1< M > >
  218. {
  219. typedef Orthogonal0< S0< M >, M, S1< M > > my_base;
  220. public:
  221. typedef sc::transition< E, S211< M > > reactions;
  222. S0( typename my_base::my_context ctx ) : my_base( ctx ) {}
  223. void Transit( const A & evt ) { TransitImpl( evt ); }
  224. void Transit( const B & evt ) { TransitImpl( evt ); }
  225. void Transit( const C & evt ) { TransitImpl( evt ); }
  226. void Transit( const D & evt ) { TransitImpl( evt ); }
  227. void Transit( const F & evt ) { TransitImpl( evt ); }
  228. void Transit( const G & evt ) { TransitImpl( evt ); }
  229. void Transit( const H & evt ) { TransitImpl( evt ); }
  230. private:
  231. template< class Event >
  232. void TransitImpl( const Event & )
  233. {
  234. this->outermost_context().template ActualTransition< S0< M >, Event >();
  235. }
  236. };
  237. template< class M > struct S11;
  238. template< class M > struct S21;
  239. template< class M >
  240. struct S2 : Orthogonal2< S2< M >, S0< M >, S21< M > >
  241. {
  242. typedef Orthogonal2< S2< M >, S0< M >, S21< M > > my_base;
  243. typedef mpl::list<
  244. sc::transition< C, S1< M >, S0< M >, &S0< M >::Transit >,
  245. sc::transition< F, S11< M >, S0< M >, &S0< M >::Transit >
  246. > reactions;
  247. S2( typename my_base::my_context ctx ) : my_base( ctx ) {}
  248. };
  249. template< class M >
  250. struct S21 : Orthogonal1<
  251. S21< M >, typename S2< M >::template orthogonal< 2 >, S211< M > >
  252. {
  253. typedef Orthogonal1<
  254. S21< M >, typename S2< M >::template orthogonal< 2 >, S211< M >
  255. > my_base;
  256. typedef mpl::list<
  257. sc::transition< H, S21< M >, S0< M >, &S0< M >::Transit >,
  258. sc::transition< B, S211< M >, S0< M >, &S0< M >::Transit >
  259. > reactions;
  260. S21( typename my_base::my_context ctx ) : my_base( ctx ) {}
  261. };
  262. template< class M >
  263. struct S211 : InnermostDefault<
  264. S211< M >, typename S21< M >::template orthogonal< 1 > >
  265. {
  266. typedef InnermostDefault<
  267. S211< M >, typename S21< M >::template orthogonal< 1 > > my_base;
  268. typedef mpl::list<
  269. sc::transition< D, S21< M >, S0< M >, &S0< M >::Transit >,
  270. sc::transition< G, S0< M > >
  271. > reactions;
  272. S211( typename my_base::my_context ctx ) : my_base( ctx ) {}
  273. };
  274. template< class M >
  275. struct S1 : Orthogonal1< S1< M >, S0< M >, S11< M > >
  276. {
  277. typedef Orthogonal1< S1< M >, S0< M >, S11< M > > my_base;
  278. typedef mpl::list<
  279. sc::transition< A, S1< M >, S0< M >, &S0< M >::Transit >,
  280. sc::transition< B, S11< M >, S0< M >, &S0< M >::Transit >,
  281. sc::transition< C, S2< M >, S0< M >, &S0< M >::Transit >,
  282. sc::transition< D, S0< M > >,
  283. sc::transition< F, S211< M >, S0< M >, &S0< M >::Transit >
  284. > reactions;
  285. S1( typename my_base::my_context ctx ) : my_base( ctx ) {}
  286. };
  287. template< class M >
  288. struct S11 : InnermostDefault<
  289. S11< M >, typename S1< M >::template orthogonal< 1 > >
  290. {
  291. typedef InnermostDefault<
  292. S11< M >, typename S1< M >::template orthogonal< 1 > > my_base;
  293. typedef mpl::list<
  294. sc::transition< G, S211< M >, S0< M >, &S0< M >::Transit >,
  295. sc::custom_reaction< H >
  296. > reactions;
  297. S11( typename my_base::my_context ctx ) : my_base( ctx ) {}
  298. sc::result react( const H & )
  299. {
  300. this->outermost_context().template ActualTransition< S11< M >, H >();
  301. return this->discard_event();
  302. }
  303. };
  304. struct X1;
  305. struct TransitionEventBaseTest :
  306. sc::state_machine< TransitionEventBaseTest, X1 >
  307. {
  308. public:
  309. TransitionEventBaseTest() : actionCallCounter_( 0 ) {}
  310. void Transit( const sc::event_base & eventBase )
  311. {
  312. BOOST_REQUIRE(
  313. ( dynamic_cast< const B * >( &eventBase ) != 0 ) ||
  314. ( dynamic_cast< const D * >( &eventBase ) != 0 ) );
  315. ++actionCallCounter_;
  316. }
  317. unsigned int GetActionCallCounter() const
  318. {
  319. return actionCallCounter_;
  320. }
  321. private:
  322. unsigned int actionCallCounter_;
  323. };
  324. struct X2 : sc::simple_state< X2, TransitionEventBaseTest >
  325. {
  326. typedef sc::transition< sc::event_base, X1,
  327. TransitionEventBaseTest, &TransitionEventBaseTest::Transit > reactions;
  328. };
  329. struct X1 : sc::simple_state< X1, TransitionEventBaseTest >
  330. {
  331. typedef sc::transition< sc::event_base, X2 > reactions;
  332. };
  333. template< class M >
  334. void TestTransitions( M & machine )
  335. {
  336. machine.initiate();
  337. ActionArray init =
  338. {
  339. Entry< S0< M > >,
  340. Entry< S1< M > >,
  341. Entry< Default0< S1< M > > >,
  342. Entry< S11< M > >,
  343. Entry< Default2< S1< M > > >,
  344. Entry< Default1< S0< M > > >,
  345. Entry< Default2< S0< M > > >
  346. };
  347. machine.CompareToExpectedActionSequence( init );
  348. machine.process_event( A() );
  349. ActionArray a1 =
  350. {
  351. Exit< Default2< S1< M > > >,
  352. Exit< S11< M > >,
  353. Exit< Default0< S1< M > > >,
  354. Exit< S1< M > >,
  355. Trans< S0< M >, A >,
  356. Entry< S1< M > >,
  357. Entry< Default0< S1< M > > >,
  358. Entry< S11< M > >,
  359. Entry< Default2< S1< M > > >
  360. };
  361. machine.CompareToExpectedActionSequence( a1 );
  362. machine.process_event( B() );
  363. ActionArray b1 =
  364. {
  365. Exit< Default2< S1< M > > >,
  366. Exit< S11< M > >,
  367. Exit< Default0< S1< M > > >,
  368. Exit< S1< M > >,
  369. Trans< S0< M >, B >,
  370. Entry< S1< M > >,
  371. Entry< Default0< S1< M > > >,
  372. Entry< S11< M > >,
  373. Entry< Default2< S1< M > > >
  374. };
  375. machine.CompareToExpectedActionSequence( b1 );
  376. machine.process_event( C() );
  377. ActionArray c1 =
  378. {
  379. Exit< Default2< S1< M > > >,
  380. Exit< S11< M > >,
  381. Exit< Default0< S1< M > > >,
  382. Exit< S1< M > >,
  383. Trans< S0< M >, C >,
  384. Entry< S2< M > >,
  385. Entry< Default0< S2< M > > >,
  386. Entry< Default1< S2< M > > >,
  387. Entry< S21< M > >,
  388. Entry< Default0< S21< M > > >,
  389. Entry< S211< M > >,
  390. Entry< Default2< S21< M > > >
  391. };
  392. machine.CompareToExpectedActionSequence( c1 );
  393. machine.process_event( D() );
  394. ActionArray d2 =
  395. {
  396. Exit< Default2< S21< M > > >,
  397. Exit< S211< M > >,
  398. Exit< Default0< S21< M > > >,
  399. Exit< S21< M > >,
  400. Trans< S0< M >, D >,
  401. Entry< S21< M > >,
  402. Entry< Default0< S21< M > > >,
  403. Entry< S211< M > >,
  404. Entry< Default2< S21< M > > >
  405. };
  406. machine.CompareToExpectedActionSequence( d2 );
  407. machine.process_event( E() );
  408. ActionArray e2 =
  409. {
  410. Exit< Default2< S0< M > > >,
  411. Exit< Default1< S0< M > > >,
  412. Exit< Default2< S21< M > > >,
  413. Exit< S211< M > >,
  414. Exit< Default0< S21< M > > >,
  415. Exit< S21< M > >,
  416. Exit< Default1< S2< M > > >,
  417. Exit< Default0< S2< M > > >,
  418. Exit< S2< M > >,
  419. Exit< S0< M > >,
  420. Entry< S0< M > >,
  421. Entry< S2< M > >,
  422. Entry< Default0< S2< M > > >,
  423. Entry< Default1< S2< M > > >,
  424. Entry< S21< M > >,
  425. Entry< Default0< S21< M > > >,
  426. Entry< S211< M > >,
  427. Entry< Default2< S21< M > > >,
  428. Entry< Default1< S0< M > > >,
  429. Entry< Default2< S0< M > > >
  430. };
  431. machine.CompareToExpectedActionSequence( e2 );
  432. machine.process_event( F() );
  433. ActionArray f2 =
  434. {
  435. Exit< Default2< S21< M > > >,
  436. Exit< S211< M > >,
  437. Exit< Default0< S21< M > > >,
  438. Exit< S21< M > >,
  439. Exit< Default1< S2< M > > >,
  440. Exit< Default0< S2< M > > >,
  441. Exit< S2< M > >,
  442. Trans< S0< M >, F >,
  443. Entry< S1< M > >,
  444. Entry< Default0< S1< M > > >,
  445. Entry< S11< M > >,
  446. Entry< Default2< S1< M > > >
  447. };
  448. machine.CompareToExpectedActionSequence( f2 );
  449. machine.process_event( G() );
  450. ActionArray g1 =
  451. {
  452. Exit< Default2< S1< M > > >,
  453. Exit< S11< M > >,
  454. Exit< Default0< S1< M > > >,
  455. Exit< S1< M > >,
  456. Trans< S0< M >, G >,
  457. Entry< S2< M > >,
  458. Entry< Default0< S2< M > > >,
  459. Entry< Default1< S2< M > > >,
  460. Entry< S21< M > >,
  461. Entry< Default0< S21< M > > >,
  462. Entry< S211< M > >,
  463. Entry< Default2< S21< M > > >
  464. };
  465. machine.CompareToExpectedActionSequence( g1 );
  466. machine.process_event( H() );
  467. ActionArray h2 =
  468. {
  469. Exit< Default2< S21< M > > >,
  470. Exit< S211< M > >,
  471. Exit< Default0< S21< M > > >,
  472. Exit< S21< M > >,
  473. Trans< S0< M >, H >,
  474. Entry< S21< M > >,
  475. Entry< Default0< S21< M > > >,
  476. Entry< S211< M > >,
  477. Entry< Default2< S21< M > > >
  478. };
  479. machine.CompareToExpectedActionSequence( h2 );
  480. BOOST_REQUIRE( machine.GetUnconsumedEventCount() == 0 );
  481. machine.process_event( A() );
  482. BOOST_REQUIRE( machine.GetUnconsumedEventCount() == 1 );
  483. ActionArray a2 =
  484. {
  485. };
  486. machine.CompareToExpectedActionSequence( a2 );
  487. machine.process_event( B() );
  488. ActionArray b2 =
  489. {
  490. Exit< Default2< S21< M > > >,
  491. Exit< S211< M > >,
  492. Exit< Default0< S21< M > > >,
  493. Exit< S21< M > >,
  494. Trans< S0< M >, B >,
  495. Entry< S21< M > >,
  496. Entry< Default0< S21< M > > >,
  497. Entry< S211< M > >,
  498. Entry< Default2< S21< M > > >
  499. };
  500. machine.CompareToExpectedActionSequence( b2 );
  501. machine.process_event( C() );
  502. ActionArray c2 =
  503. {
  504. Exit< Default2< S21< M > > >,
  505. Exit< S211< M > >,
  506. Exit< Default0< S21< M > > >,
  507. Exit< S21< M > >,
  508. Exit< Default1< S2< M > > >,
  509. Exit< Default0< S2< M > > >,
  510. Exit< S2< M > >,
  511. Trans< S0< M >, C >,
  512. Entry< S1< M > >,
  513. Entry< Default0< S1< M > > >,
  514. Entry< S11< M > >,
  515. Entry< Default2< S1< M > > >
  516. };
  517. machine.CompareToExpectedActionSequence( c2 );
  518. machine.process_event( D() );
  519. ActionArray d1 =
  520. {
  521. Exit< Default2< S0< M > > >,
  522. Exit< Default1< S0< M > > >,
  523. Exit< Default2< S1< M > > >,
  524. Exit< S11< M > >,
  525. Exit< Default0< S1< M > > >,
  526. Exit< S1< M > >,
  527. Exit< S0< M > >,
  528. Entry< S0< M > >,
  529. Entry< S1< M > >,
  530. Entry< Default0< S1< M > > >,
  531. Entry< S11< M > >,
  532. Entry< Default2< S1< M > > >,
  533. Entry< Default1< S0< M > > >,
  534. Entry< Default2< S0< M > > >
  535. };
  536. machine.CompareToExpectedActionSequence( d1 );
  537. machine.process_event( F() );
  538. ActionArray f1 =
  539. {
  540. Exit< Default2< S1< M > > >,
  541. Exit< S11< M > >,
  542. Exit< Default0< S1< M > > >,
  543. Exit< S1< M > >,
  544. Trans< S0< M >, F >,
  545. Entry< S2< M > >,
  546. Entry< Default0< S2< M > > >,
  547. Entry< Default1< S2< M > > >,
  548. Entry< S21< M > >,
  549. Entry< Default0< S21< M > > >,
  550. Entry< S211< M > >,
  551. Entry< Default2< S21< M > > >
  552. };
  553. machine.CompareToExpectedActionSequence( f1 );
  554. machine.process_event( G() );
  555. ActionArray g2 =
  556. {
  557. Exit< Default2< S0< M > > >,
  558. Exit< Default1< S0< M > > >,
  559. Exit< Default2< S21< M > > >,
  560. Exit< S211< M > >,
  561. Exit< Default0< S21< M > > >,
  562. Exit< S21< M > >,
  563. Exit< Default1< S2< M > > >,
  564. Exit< Default0< S2< M > > >,
  565. Exit< S2< M > >,
  566. Exit< S0< M > >,
  567. Entry< S0< M > >,
  568. Entry< S1< M > >,
  569. Entry< Default0< S1< M > > >,
  570. Entry< S11< M > >,
  571. Entry< Default2< S1< M > > >,
  572. Entry< Default1< S0< M > > >,
  573. Entry< Default2< S0< M > > >
  574. };
  575. machine.CompareToExpectedActionSequence( g2 );
  576. machine.process_event( H() );
  577. ActionArray h1 =
  578. {
  579. Trans< S11< M >, H >
  580. };
  581. machine.CompareToExpectedActionSequence( h1 );
  582. machine.process_event( E() );
  583. ActionArray e1 =
  584. {
  585. Exit< Default2< S0< M > > >,
  586. Exit< Default1< S0< M > > >,
  587. Exit< Default2< S1< M > > >,
  588. Exit< S11< M > >,
  589. Exit< Default0< S1< M > > >,
  590. Exit< S1< M > >,
  591. Exit< S0< M > >,
  592. Entry< S0< M > >,
  593. Entry< S2< M > >,
  594. Entry< Default0< S2< M > > >,
  595. Entry< Default1< S2< M > > >,
  596. Entry< S21< M > >,
  597. Entry< Default0< S21< M > > >,
  598. Entry< S211< M > >,
  599. Entry< Default2< S21< M > > >,
  600. Entry< Default1< S0< M > > >,
  601. Entry< Default2< S0< M > > >
  602. };
  603. machine.CompareToExpectedActionSequence( e1 );
  604. machine.terminate();
  605. ActionArray term =
  606. {
  607. Exit< Default2< S0< M > > >,
  608. Exit< Default1< S0< M > > >,
  609. Exit< Default2< S21< M > > >,
  610. Exit< S211< M > >,
  611. Exit< Default0< S21< M > > >,
  612. Exit< S21< M > >,
  613. Exit< Default1< S2< M > > >,
  614. Exit< Default0< S2< M > > >,
  615. Exit< S2< M > >,
  616. Exit< S0< M > >
  617. };
  618. machine.CompareToExpectedActionSequence( term );
  619. machine.ThrowAction( &Entry< Default0< S1< M > > > );
  620. BOOST_REQUIRE_THROW( machine.initiate(), TransitionTestException );
  621. ActionArray initThrow1 =
  622. {
  623. Entry< S0< M > >,
  624. Entry< S1< M > >,
  625. &::Throw< &::Entry< Default0< S1< M > > > >,
  626. Dtor< S1< M > >,
  627. Dtor< S0< M > >
  628. };
  629. machine.CompareToExpectedActionSequence( initThrow1 );
  630. BOOST_REQUIRE( machine.terminated() );
  631. machine.ThrowAction( &Entry< S11< M > > );
  632. BOOST_REQUIRE_THROW( machine.initiate(), TransitionTestException );
  633. ActionArray initThrow2 =
  634. {
  635. Entry< S0< M > >,
  636. Entry< S1< M > >,
  637. Entry< Default0< S1< M > > >,
  638. &::Throw< &::Entry< S11< M > > >,
  639. Dtor< Default0< S1< M > > >,
  640. Dtor< S1< M > >,
  641. Dtor< S0< M > >
  642. };
  643. machine.CompareToExpectedActionSequence( initThrow2 );
  644. BOOST_REQUIRE( machine.terminated() );
  645. machine.ThrowAction( &Trans< S0< M >, A > );
  646. machine.initiate();
  647. BOOST_REQUIRE_THROW( machine.process_event( A() ), TransitionTestException );
  648. ActionArray a1Throw1 =
  649. {
  650. Entry< S0< M > >,
  651. Entry< S1< M > >,
  652. Entry< Default0< S1< M > > >,
  653. Entry< S11< M > >,
  654. Entry< Default2< S1< M > > >,
  655. Entry< Default1< S0< M > > >,
  656. Entry< Default2< S0< M > > >,
  657. Exit< Default2< S1< M > > >,
  658. Exit< S11< M > >,
  659. Exit< Default0< S1< M > > >,
  660. Exit< S1< M > >,
  661. &::Throw< &::Trans< S0< M >, A > >,
  662. Dtor< Default2< S0< M > > >,
  663. Dtor< Default1< S0< M > > >,
  664. Dtor< S0< M > >
  665. };
  666. machine.CompareToExpectedActionSequence( a1Throw1 );
  667. BOOST_REQUIRE( machine.terminated() );
  668. machine.ThrowAction( &Entry< S211< M > > );
  669. machine.initiate();
  670. BOOST_REQUIRE_THROW( machine.process_event( C() ), TransitionTestException );
  671. ActionArray c1Throw1 =
  672. {
  673. Entry< S0< M > >,
  674. Entry< S1< M > >,
  675. Entry< Default0< S1< M > > >,
  676. Entry< S11< M > >,
  677. Entry< Default2< S1< M > > >,
  678. Entry< Default1< S0< M > > >,
  679. Entry< Default2< S0< M > > >,
  680. Exit< Default2< S1< M > > >,
  681. Exit< S11< M > >,
  682. Exit< Default0< S1< M > > >,
  683. Exit< S1< M > >,
  684. Trans< S0< M >, C >,
  685. Entry< S2< M > >,
  686. Entry< Default0< S2< M > > >,
  687. Entry< Default1< S2< M > > >,
  688. Entry< S21< M > >,
  689. Entry< Default0< S21< M > > >,
  690. &::Throw< &::Entry< S211< M > > >,
  691. Dtor< Default2< S0< M > > >,
  692. Dtor< Default1< S0< M > > >,
  693. Dtor< Default0< S21< M > > >,
  694. Dtor< S21< M > >,
  695. Dtor< Default1< S2< M > > >,
  696. Dtor< Default0< S2< M > > >,
  697. Dtor< S2< M > >,
  698. Dtor< S0< M > >
  699. };
  700. machine.CompareToExpectedActionSequence( c1Throw1 );
  701. BOOST_REQUIRE( machine.terminated() );
  702. machine.ThrowAction( &ExitFn< S11< M > > );
  703. machine.initiate();
  704. BOOST_REQUIRE_THROW( machine.process_event( C() ), TransitionTestException );
  705. ActionArray c1Throw2 =
  706. {
  707. Entry< S0< M > >,
  708. Entry< S1< M > >,
  709. Entry< Default0< S1< M > > >,
  710. Entry< S11< M > >,
  711. Entry< Default2< S1< M > > >,
  712. Entry< Default1< S0< M > > >,
  713. Entry< Default2< S0< M > > >,
  714. Exit< Default2< S1< M > > >,
  715. &::Throw< &::ExitFn< S11< M > > >,
  716. Dtor< S11< M > >,
  717. Dtor< Default2< S0< M > > >,
  718. Dtor< Default1< S0< M > > >,
  719. Dtor< Default0< S1< M > > >,
  720. Dtor< S1< M > >,
  721. Dtor< S0< M > >
  722. };
  723. machine.CompareToExpectedActionSequence( c1Throw2 );
  724. BOOST_REQUIRE( machine.terminated() );
  725. BOOST_REQUIRE( machine.GetUnconsumedEventCount() == 1 );
  726. }
  727. int test_main( int, char* [] )
  728. {
  729. TransitionTest< sc::null_exception_translator > null_machine;
  730. TestTransitions( null_machine );
  731. TransitionTest< sc::exception_translator<> > machine;
  732. TestTransitions( machine );
  733. TransitionEventBaseTest eventBaseMachine;
  734. eventBaseMachine.initiate();
  735. BOOST_REQUIRE_NO_THROW( eventBaseMachine.state_cast< const X1 & >() );
  736. eventBaseMachine.process_event( A() );
  737. BOOST_REQUIRE_NO_THROW( eventBaseMachine.state_cast< const X2 & >() );
  738. BOOST_REQUIRE( eventBaseMachine.GetActionCallCounter() == 0 );
  739. eventBaseMachine.process_event( B() );
  740. BOOST_REQUIRE_NO_THROW( eventBaseMachine.state_cast< const X1 & >() );
  741. BOOST_REQUIRE( eventBaseMachine.GetActionCallCounter() == 1 );
  742. eventBaseMachine.process_event( C() );
  743. BOOST_REQUIRE_NO_THROW( eventBaseMachine.state_cast< const X2 & >() );
  744. BOOST_REQUIRE( eventBaseMachine.GetActionCallCounter() == 1 );
  745. eventBaseMachine.process_event( D() );
  746. BOOST_REQUIRE_NO_THROW( eventBaseMachine.state_cast< const X1 & >() );
  747. BOOST_REQUIRE( eventBaseMachine.GetActionCallCounter() == 2 );
  748. return 0;
  749. }