////////////////////////////////////////////////////////////////////////////// // 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 #include #include #include #include #include #include #include #include namespace sc = boost::statechart; namespace mpl = boost::mpl; struct EvToB : sc::event< EvToB > {}; struct EvToF : sc::event< EvToF > {}; struct EvCheck : sc::event< EvCheck > {}; struct A; struct StateCastTest : sc::state_machine< StateCastTest, A > { template< class State > void AssertInState() { BOOST_REQUIRE( state_downcast< const State * >() != 0 ); BOOST_REQUIRE_NO_THROW( state_downcast< const State & >() ); BOOST_REQUIRE( state_cast< const State * >() != 0 ); BOOST_REQUIRE_NO_THROW( state_cast< const State & >() ); } template< class State > void AssertNotInState() { BOOST_REQUIRE( state_downcast< const State * >() == 0 ); BOOST_REQUIRE_THROW( state_downcast< const State & >(), std::bad_cast ); BOOST_REQUIRE( state_cast< const State * >() == 0 ); BOOST_REQUIRE_THROW( state_cast< const State & >(), std::bad_cast ); } }; template< class State, class FromState > void AssertInState( const FromState & theState ) { BOOST_REQUIRE( theState.template state_downcast< const State * >() != 0 ); BOOST_REQUIRE_NO_THROW( theState.template state_downcast< const State & >() ); BOOST_REQUIRE( theState.template state_cast< const State * >() != 0 ); BOOST_REQUIRE_NO_THROW( theState.template state_cast< const State & >() ); } template< class State, class FromState > void AssertNotInState( const FromState & theState ) { BOOST_REQUIRE( theState.template state_downcast< const State * >() == 0 ); BOOST_REQUIRE_THROW( theState.template state_downcast< const State & >(), std::bad_cast ); BOOST_REQUIRE( theState.template state_cast< const State * >() == 0 ); BOOST_REQUIRE_THROW( theState.template state_cast< const State & >(), std::bad_cast ); } struct B; struct C; struct D; struct A : sc::simple_state< A, StateCastTest, mpl::list< C, D > > { typedef sc::transition< EvToB, B > reactions; }; struct E; struct C : sc::simple_state< C, A::orthogonal< 0 >, E > {}; struct E : sc::state< E, C > { typedef sc::custom_reaction< EvCheck > reactions; E( my_context ctx ) : my_base( ctx ) { post_event( boost::intrusive_ptr< EvCheck >( new EvCheck() ) ); } sc::result react( const EvCheck & ); }; struct F : sc::state< F, C > { typedef sc::custom_reaction< EvCheck > reactions; F( my_context ctx ) : my_base( ctx ) { post_event( boost::intrusive_ptr< EvCheck >( new EvCheck() ) ); } sc::result react( const EvCheck & ); }; struct G; struct D : sc::simple_state< D, A::orthogonal< 1 >, G > {}; struct G : sc::simple_state< G, D > {}; struct H : sc::simple_state< H, D > {}; struct B : sc::simple_state< B, StateCastTest > { typedef sc::transition< EvToF, F > reactions; }; sc::result E::react( const EvCheck & ) { AssertInState< A >( *this ); AssertNotInState< B >( *this ); AssertInState< C >( *this ); AssertInState< D >( *this ); AssertInState< E >( *this ); AssertNotInState< F >( *this ); AssertInState< G >( *this ); AssertNotInState< H >( *this ); return discard_event(); } sc::result F::react( const EvCheck & ) { AssertInState< A >( *this ); AssertNotInState< B >( *this ); AssertInState< C >( *this ); AssertInState< D >( *this ); AssertNotInState< E >( *this ); AssertInState< F >( *this ); AssertInState< G >( *this ); AssertNotInState< H >( *this ); return discard_event(); } int test_main( int, char* [] ) { StateCastTest machine; machine.AssertNotInState< A >(); machine.AssertNotInState< B >(); machine.AssertNotInState< C >(); machine.AssertNotInState< D >(); machine.AssertNotInState< E >(); machine.AssertNotInState< F >(); machine.AssertNotInState< G >(); machine.AssertNotInState< H >(); machine.initiate(); machine.AssertInState< A >(); machine.AssertNotInState< B >(); machine.AssertInState< C >(); machine.AssertInState< D >(); machine.AssertInState< E >(); machine.AssertNotInState< F >(); machine.AssertInState< G >(); machine.AssertNotInState< H >(); machine.process_event( EvToB() ); machine.AssertNotInState< A >(); machine.AssertInState< B >(); machine.AssertNotInState< C >(); machine.AssertNotInState< D >(); machine.AssertNotInState< E >(); machine.AssertNotInState< F >(); machine.AssertNotInState< G >(); machine.AssertNotInState< H >(); machine.process_event( EvToF() ); machine.AssertInState< A >(); machine.AssertNotInState< B >(); machine.AssertInState< C >(); machine.AssertInState< D >(); machine.AssertNotInState< E >(); machine.AssertInState< F >(); machine.AssertInState< G >(); machine.AssertNotInState< H >(); machine.terminate(); machine.AssertNotInState< A >(); machine.AssertNotInState< B >(); machine.AssertNotInState< C >(); machine.AssertNotInState< D >(); machine.AssertNotInState< E >(); machine.AssertNotInState< F >(); machine.AssertNotInState< G >(); machine.AssertNotInState< H >(); return 0; }