📄 customreactiontest.cpp
字号:
//////////////////////////////////////////////////////////////////////////////// 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/transition.hpp>#include <boost/statechart/custom_reaction.hpp>#include <boost/mpl/list.hpp>#include <boost/test/test_tools.hpp>#include <set>#include <map>#include <string>#include <cstddef> // size_tnamespace sc = boost::statechart;namespace mpl = boost::mpl;struct EvToC : sc::event< EvToC > {};struct EvToD : sc::event< EvToD > {};struct EvDiscardNever : sc::event< EvDiscardNever > {};struct EvDiscardInB : sc::event< EvDiscardInB > {};struct EvDiscardInD : sc::event< EvDiscardInD > {};struct EvTransit : sc::event< EvTransit > {};struct EvTransitWithAction : sc::event< EvTransitWithAction > {};struct EvDefer : sc::event< EvDefer > {};struct EvTerminate : sc::event< EvTerminate > {};struct A;struct CustomReactionTest : sc::state_machine< CustomReactionTest, A >{ public: ////////////////////////////////////////////////////////////////////////// CustomReactionTest(); void Visited( const state_base_type & stt ) { const StateNamesMap::const_iterator found = stateNamesMap_.find( stt.dynamic_type() ); BOOST_REQUIRE( found != stateNamesMap_.end() ); visitedStates_.insert( found->second ); } void ClearVisited() { visitedStates_.clear(); } void AssertVisitedAll( const std::string & stateNames ) const { for ( std::string::const_iterator expectedName = stateNames.begin(); expectedName != stateNames.end(); ++expectedName ) { BOOST_REQUIRE( visitedStates_.find( std::string( 1, *expectedName ) ) != visitedStates_.end() ); } } void AssertVisitedOne( const std::string & stateNames ) const { std::size_t found = 0; for ( std::string::const_iterator actualName = stateNames.begin(); actualName != stateNames.end(); ++actualName ) { found = found + ( visitedStates_.find( std::string( 1, *actualName ) ) != visitedStates_.end() ) ? 1 : 0; } BOOST_REQUIRE( found == 1 ); } void TransitionAction( const EvTransitWithAction & ) {} private: ////////////////////////////////////////////////////////////////////////// typedef std::map< state_base_type::id_type, std::string > StateNamesMap; typedef std::set< std::string > VisitedStates; StateNamesMap stateNamesMap_; VisitedStates visitedStates_;};struct B;struct A : sc::simple_state< A, CustomReactionTest, B >{ typedef mpl::list< sc::custom_reaction< EvDiscardNever >, sc::custom_reaction< EvDiscardInB >, sc::custom_reaction< EvDiscardInD >, sc::custom_reaction< EvDefer >, sc::custom_reaction< EvTerminate >, sc::custom_reaction< EvTransitWithAction >, sc::custom_reaction< EvTransit > > reactions; sc::result react( const EvDiscardNever & ) { outermost_context().Visited( *this ); return forward_event(); } sc::result react( const EvDiscardInB & ) { BOOST_FAIL( "An event discarded in B must never reach A" ); return discard_event(); } sc::result react( const EvDiscardInD & ) { BOOST_FAIL( "An event discarded in D must never reach B" ); return discard_event(); } // The following code is here just to make sure that calls to the transit<>, // defer_event and terminate functions actually compile. // Their functionality is tested extensively in TransitionTest, // DeferralTest and TerminationTest with appropriate reactions. Internally, // these reactions call exactly the same functions as the following custom // reactions call. sc::result react( const EvDefer & ) { return defer_event(); } sc::result react( const EvTerminate & ) { return terminate(); } sc::result react( const EvTransit & ) { return transit< A >(); } sc::result react( const EvTransitWithAction & evt ) { return transit< A >( &CustomReactionTest::TransitionAction, evt ); }}; struct C; struct B : sc::simple_state< B, A, C > { typedef mpl::list< sc::custom_reaction< EvDiscardNever >, sc::custom_reaction< EvDiscardInB >, sc::custom_reaction< EvDiscardInD > > reactions; sc::result react( const EvDiscardNever & ) { outermost_context().Visited( *this ); return forward_event(); } sc::result react( const EvDiscardInB & ) { outermost_context().Visited( *this ); return discard_event(); } sc::result react( const EvDiscardInD & ) { BOOST_FAIL( "An event discarded in D must never reach B" ); return discard_event(); } }; struct E; struct F; struct D : sc::simple_state< D, B, mpl::list< E, F > > { typedef mpl::list< sc::transition< EvToC, C >, sc::custom_reaction< EvDiscardNever >, sc::custom_reaction< EvDiscardInB >, sc::custom_reaction< EvDiscardInD > > reactions; sc::result react( const EvDiscardNever & ) { outermost_context().Visited( *this ); return forward_event(); } sc::result react( const EvDiscardInB & ) { outermost_context().Visited( *this ); return forward_event(); } sc::result react( const EvDiscardInD & ) { outermost_context().Visited( *this ); return discard_event(); } }; struct E : sc::simple_state< E, D::orthogonal< 0 > > { typedef mpl::list< sc::custom_reaction< EvDiscardNever >, sc::custom_reaction< EvDiscardInB >, sc::custom_reaction< EvDiscardInD > > reactions; sc::result react( const EvDiscardNever & ) { outermost_context().Visited( *this ); return forward_event(); } sc::result react( const EvDiscardInB & ) { outermost_context().Visited( *this ); return forward_event(); } sc::result react( const EvDiscardInD & ) { outermost_context().Visited( *this ); return forward_event(); } }; struct F : sc::simple_state< F, D::orthogonal< 1 > > { typedef mpl::list< sc::custom_reaction< EvDiscardNever >, sc::custom_reaction< EvDiscardInB >, sc::custom_reaction< EvDiscardInD > > reactions; sc::result react( const EvDiscardNever & ) { outermost_context().Visited( *this ); return forward_event(); } sc::result react( const EvDiscardInB & ) { outermost_context().Visited( *this ); return forward_event(); } sc::result react( const EvDiscardInD & ) { outermost_context().Visited( *this ); return forward_event(); } }; struct C : sc::simple_state< C, B > { typedef mpl::list< sc::transition< EvToD, D >, sc::custom_reaction< EvDiscardNever >, sc::custom_reaction< EvDiscardInB >, sc::custom_reaction< EvDiscardInD > > reactions; sc::result react( const EvDiscardNever & ) { outermost_context().Visited( *this ); return forward_event(); } sc::result react( const EvDiscardInB & ) { outermost_context().Visited( *this ); return forward_event(); } sc::result react( const EvDiscardInD & ) { outermost_context().Visited( *this ); return forward_event(); } };CustomReactionTest::CustomReactionTest(){ // 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";}struct X1;struct CustomReactionEventBaseTest : sc::state_machine< CustomReactionEventBaseTest, X1 >{ public: CustomReactionEventBaseTest() : reactionCount_( 0 ) {} void IncrementReactionCount() { ++reactionCount_; } unsigned int GetReactionCount() const { return reactionCount_; } private: unsigned int reactionCount_;};struct X1 : sc::simple_state< X1, CustomReactionEventBaseTest >{ typedef sc::custom_reaction< sc::event_base > reactions; sc::result react( const sc::event_base & ) { outermost_context().IncrementReactionCount(); return discard_event(); }};int test_main( int, char* [] ){ CustomReactionTest machine; machine.initiate(); machine.process_event( EvDiscardNever() ); machine.AssertVisitedAll( "ABC" ); machine.ClearVisited(); machine.process_event( EvDiscardInB() ); machine.AssertVisitedAll( "BC" ); machine.process_event( EvToD() ); machine.ClearVisited(); machine.process_event( EvDiscardNever() ); machine.AssertVisitedAll( "ABDEF" ); machine.ClearVisited(); machine.process_event( EvDiscardInD() ); machine.AssertVisitedAll( "D" ); machine.AssertVisitedOne( "EF" ); machine.ClearVisited(); machine.process_event( EvDiscardInB() ); machine.AssertVisitedAll( "BD" ); machine.AssertVisitedOne( "EF" ); machine.ClearVisited(); CustomReactionEventBaseTest eventBaseMachine; eventBaseMachine.initiate(); BOOST_REQUIRE( eventBaseMachine.GetReactionCount() == 0 ); eventBaseMachine.process_event( EvToC() ); BOOST_REQUIRE( eventBaseMachine.GetReactionCount() == 1 ); eventBaseMachine.process_event( EvToD() ); BOOST_REQUIRE( eventBaseMachine.GetReactionCount() == 2 ); return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -