summaryrefslogtreecommitdiffstats
path: root/src/boost/libs/statechart/test/CustomReactionTest.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/boost/libs/statechart/test/CustomReactionTest.cpp')
-rw-r--r--src/boost/libs/statechart/test/CustomReactionTest.cpp381
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;
+}