diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-21 11:54:28 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-21 11:54:28 +0000 |
commit | e6918187568dbd01842d8d1d2c808ce16a894239 (patch) | |
tree | 64f88b554b444a49f656b6c656111a145cbbaa28 /src/boost/libs/statechart/test/CustomReactionTest.cpp | |
parent | Initial commit. (diff) | |
download | ceph-e6918187568dbd01842d8d1d2c808ce16a894239.tar.xz ceph-e6918187568dbd01842d8d1d2c808ce16a894239.zip |
Adding upstream version 18.2.2.upstream/18.2.2
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/boost/libs/statechart/test/CustomReactionTest.cpp')
-rw-r--r-- | src/boost/libs/statechart/test/CustomReactionTest.cpp | 381 |
1 files changed, 381 insertions, 0 deletions
diff --git a/src/boost/libs/statechart/test/CustomReactionTest.cpp b/src/boost/libs/statechart/test/CustomReactionTest.cpp new file mode 100644 index 000000000..3dbabbf50 --- /dev/null +++ b/src/boost/libs/statechart/test/CustomReactionTest.cpp @@ -0,0 +1,381 @@ +////////////////////////////////////////////////////////////////////////////// +// 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_t + + + +namespace 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; +} |