123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283 |
- //////////////////////////////////////////////////////////////////////////////
- // Copyright 2005-2006 Andreas Huber Doenni
- // Distributed under the Boost Software License, Version 1.0. (See accompany-
- // ing file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
- //////////////////////////////////////////////////////////////////////////////
- #include <boost/statechart/state_machine.hpp>
- #include <boost/statechart/event.hpp>
- #include <boost/statechart/simple_state.hpp>
- #include <boost/statechart/termination.hpp>
- #include <boost/mpl/list.hpp>
- #include <boost/test/test_tools.hpp>
- #include <set>
- #include <map>
- #include <string>
- namespace sc = boost::statechart;
- namespace mpl = boost::mpl;
- struct EvTerminateA : sc::event< EvTerminateA > {};
- struct EvTerminateB : sc::event< EvTerminateB > {};
- struct EvTerminateC : sc::event< EvTerminateC > {};
- struct EvTerminateD : sc::event< EvTerminateD > {};
- struct EvTerminateE : sc::event< EvTerminateE > {};
- struct EvTerminateF : sc::event< EvTerminateF > {};
- struct EvTerminateG : sc::event< EvTerminateG > {};
- struct A;
- struct TerminationTest : sc::state_machine< TerminationTest, A >
- {
- public:
- //////////////////////////////////////////////////////////////////////////
- TerminationTest();
- void AssertInState( const std::string & stateNames ) const
- {
- stateNamesCache_.clear();
- for ( state_iterator currentState = state_begin();
- currentState != state_end(); ++currentState )
- {
- AddName( currentState->dynamic_type() );
- const state_base_type * outerState = currentState->outer_state_ptr();
- while ( outerState != 0 )
- {
- AddName( outerState->dynamic_type() );
- outerState = outerState->outer_state_ptr();
- }
- }
- std::string::const_iterator expectedName = stateNames.begin();
- BOOST_REQUIRE( stateNames.size() == stateNamesCache_.size() );
- for ( StateNamesCache::const_iterator actualName =
- stateNamesCache_.begin(); actualName != stateNamesCache_.end();
- ++actualName, ++expectedName )
- {
- BOOST_REQUIRE( ( *actualName )[ 0 ] == *expectedName );
- }
- }
- private:
- //////////////////////////////////////////////////////////////////////////
- void AddName( state_base_type::id_type stateType ) const
- {
- const StateNamesMap::const_iterator found =
- stateNamesMap_.find( stateType );
- BOOST_REQUIRE( found != stateNamesMap_.end() );
- stateNamesCache_.insert( found->second );
- }
- typedef std::map< state_base_type::id_type, std::string > StateNamesMap;
- typedef std::set< std::string > StateNamesCache;
- StateNamesMap stateNamesMap_;
- mutable StateNamesCache stateNamesCache_;
- };
- template<
- class MostDerived,
- class Context,
- class InnerInitial = mpl::list<> >
- struct MyState : sc::simple_state< MostDerived, Context, InnerInitial >
- {
- public:
- MyState() : exitCalled_( false ) {}
- ~MyState()
- {
- // BOOST_REQUIRE throws an exception when the test fails. If the state
- // is destructed as part of a stack unwind, abort() is called what is
- // presumably also detected by the test monitor.
- BOOST_REQUIRE( exitCalled_ );
- }
- void exit()
- {
- exitCalled_ = true;
- }
- private:
- bool exitCalled_;
- };
- struct B;
- struct C;
- struct A : MyState< A, TerminationTest, mpl::list< B, C > >
- {
- typedef sc::termination< EvTerminateA > reactions;
- };
- struct B : MyState< B, A::orthogonal< 0 > >
- {
- typedef sc::termination< EvTerminateB > reactions;
- };
- struct D;
- struct E;
- struct C : MyState< C, A::orthogonal< 1 >, mpl::list< D, E > >
- {
- typedef sc::termination< EvTerminateC > reactions;
- };
- struct D : MyState< D, C::orthogonal< 0 > >
- {
- typedef sc::termination< EvTerminateD > reactions;
- };
- struct F;
- struct G;
- struct E : MyState< E, C::orthogonal< 1 >, mpl::list< F, G > >
- {
- typedef sc::termination< EvTerminateE > reactions;
- };
- struct F : MyState< F, E::orthogonal< 0 > >
- {
- typedef sc::termination< EvTerminateF > reactions;
- };
- struct G : MyState< G, E::orthogonal< 1 > >
- {
- typedef sc::termination< EvTerminateG > reactions;
- };
- TerminationTest::TerminationTest()
- {
- // We're not using custom type information to make this test work even when
- // BOOST_STATECHART_USE_NATIVE_RTTI is defined
- stateNamesMap_[ A::static_type() ] = "A";
- stateNamesMap_[ B::static_type() ] = "B";
- stateNamesMap_[ C::static_type() ] = "C";
- stateNamesMap_[ D::static_type() ] = "D";
- stateNamesMap_[ E::static_type() ] = "E";
- stateNamesMap_[ F::static_type() ] = "F";
- stateNamesMap_[ G::static_type() ] = "G";
- }
- struct X;
- struct TerminationEventBaseTest :
- sc::state_machine< TerminationEventBaseTest, X > {};
- struct X : sc::simple_state< X, TerminationEventBaseTest >
- {
- typedef sc::termination< sc::event_base > reactions;
- };
- int test_main( int, char* [] )
- {
- TerminationTest machine;
- machine.AssertInState( "" );
- machine.initiate();
- machine.AssertInState( "ABCDEFG" );
- machine.process_event( EvTerminateE() );
- machine.AssertInState( "ABCD" );
- machine.process_event( EvTerminateE() );
- machine.AssertInState( "ABCD" );
- machine.initiate();
- machine.AssertInState( "ABCDEFG" );
- machine.process_event( EvTerminateC() );
- machine.AssertInState( "AB" );
- machine.process_event( EvTerminateC() );
- machine.AssertInState( "AB" );
- machine.initiate();
- machine.AssertInState( "ABCDEFG" );
- machine.process_event( EvTerminateA() );
- machine.AssertInState( "" );
- machine.process_event( EvTerminateA() );
- machine.AssertInState( "" );
- machine.initiate();
- machine.AssertInState( "ABCDEFG" );
- machine.process_event( EvTerminateG() );
- machine.AssertInState( "ABCDEF" );
- machine.process_event( EvTerminateG() );
- machine.AssertInState( "ABCDEF" );
- machine.process_event( EvTerminateF() );
- machine.AssertInState( "ABCD" );
- machine.process_event( EvTerminateF() );
- machine.AssertInState( "ABCD" );
- machine.process_event( EvTerminateD() );
- machine.AssertInState( "AB" );
- machine.process_event( EvTerminateD() );
- machine.AssertInState( "AB" );
- machine.process_event( EvTerminateB() );
- machine.AssertInState( "" );
- machine.process_event( EvTerminateB() );
- machine.AssertInState( "" );
- machine.initiate();
- machine.AssertInState( "ABCDEFG" );
- machine.process_event( EvTerminateB() );
- machine.AssertInState( "ACDEFG" );
- machine.process_event( EvTerminateB() );
- machine.AssertInState( "ACDEFG" );
- machine.process_event( EvTerminateD() );
- machine.AssertInState( "ACEFG" );
- machine.process_event( EvTerminateD() );
- machine.AssertInState( "ACEFG" );
- machine.process_event( EvTerminateF() );
- machine.AssertInState( "ACEG" );
- machine.process_event( EvTerminateF() );
- machine.AssertInState( "ACEG" );
- machine.process_event( EvTerminateG() );
- machine.AssertInState( "" );
- machine.process_event( EvTerminateG() );
- machine.AssertInState( "" );
- machine.initiate();
- machine.AssertInState( "ABCDEFG" );
- machine.process_event( EvTerminateE() );
- machine.AssertInState( "ABCD" );
- machine.process_event( EvTerminateE() );
- machine.AssertInState( "ABCD" );
- machine.process_event( EvTerminateC() );
- machine.AssertInState( "AB" );
- machine.process_event( EvTerminateC() );
- machine.AssertInState( "AB" );
- machine.process_event( EvTerminateA() );
- machine.AssertInState( "" );
- machine.process_event( EvTerminateA() );
- machine.AssertInState( "" );
- machine.initiate();
- machine.AssertInState( "ABCDEFG" );
- machine.initiate();
- machine.AssertInState( "ABCDEFG" );
- machine.terminate();
- machine.AssertInState( "" );
- machine.terminate();
- machine.AssertInState( "" );
- TerminationEventBaseTest eventBaseMachine;
- eventBaseMachine.initiate();
- BOOST_REQUIRE( !eventBaseMachine.terminated() );
- eventBaseMachine.process_event( EvTerminateA() );
- BOOST_REQUIRE( eventBaseMachine.terminated() );
- eventBaseMachine.initiate();
- BOOST_REQUIRE( !eventBaseMachine.terminated() );
- eventBaseMachine.process_event( EvTerminateB() );
- BOOST_REQUIRE( eventBaseMachine.terminated() );
- return 0;
- }
|