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