Blame libs/statechart/test/DeferralTest.cpp

Packit 58578d
//////////////////////////////////////////////////////////////////////////////
Packit 58578d
// Copyright 2004-2006 Andreas Huber Doenni
Packit 58578d
// Distributed under the Boost Software License, Version 1.0. (See accompany-
Packit 58578d
// ing file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
Packit 58578d
//////////////////////////////////////////////////////////////////////////////
Packit 58578d
Packit 58578d
Packit 58578d
Packit 58578d
#include <boost/statechart/state_machine.hpp>
Packit 58578d
#include <boost/statechart/event.hpp>
Packit 58578d
#include <boost/statechart/simple_state.hpp>
Packit 58578d
#include <boost/statechart/transition.hpp>
Packit 58578d
#include <boost/statechart/deferral.hpp>
Packit 58578d
#include <boost/statechart/custom_reaction.hpp>
Packit 58578d
Packit 58578d
#include <boost/mpl/list.hpp>
Packit 58578d
#include <boost/intrusive_ptr.hpp>
Packit 58578d
Packit 58578d
#include <boost/test/test_tools.hpp>
Packit 58578d
Packit 58578d
Packit 58578d
Packit 58578d
namespace sc = boost::statechart;
Packit 58578d
namespace mpl = boost::mpl;
Packit 58578d
Packit 58578d
Packit 58578d
Packit 58578d
template< class T >
Packit 58578d
boost::intrusive_ptr< T > MakeIntrusive( T * pT )
Packit 58578d
{
Packit 58578d
  return boost::intrusive_ptr< T >( pT );
Packit 58578d
}
Packit 58578d
Packit 58578d
struct EvLeafDeferred : sc::event< EvLeafDeferred > {};
Packit 58578d
struct EvNodeDeferred : sc::event< EvNodeDeferred > {};
Packit 58578d
struct EvSwitch : sc::event< EvSwitch > {};
Packit 58578d
struct EvDestroy : sc::event< EvDestroy > {};
Packit 58578d
Packit 58578d
struct Active;
Packit 58578d
struct DeferralTest : sc::state_machine< DeferralTest, Active >
Packit 58578d
{
Packit 58578d
    //////////////////////////////////////////////////////////////////////////
Packit 58578d
    DeferralTest() : processedCount_( 0 ) {}
Packit 58578d
Packit 58578d
    void IncrementProcessedCount()
Packit 58578d
    {
Packit 58578d
      ++processedCount_;
Packit 58578d
    }
Packit 58578d
Packit 58578d
    unsigned int ProcessedCount() const
Packit 58578d
    {
Packit 58578d
      return processedCount_;
Packit 58578d
    }
Packit 58578d
Packit 58578d
  private:
Packit 58578d
    //////////////////////////////////////////////////////////////////////////
Packit 58578d
    unsigned int processedCount_;
Packit 58578d
};
Packit 58578d
Packit 58578d
struct Dead : sc::simple_state< Dead, DeferralTest >
Packit 58578d
{
Packit 58578d
  typedef sc::custom_reaction< EvNodeDeferred > reactions;
Packit 58578d
Packit 58578d
  sc::result react( const EvNodeDeferred & )
Packit 58578d
  {
Packit 58578d
    outermost_context().IncrementProcessedCount();
Packit 58578d
    return discard_event();
Packit 58578d
  }
Packit 58578d
};
Packit 58578d
Packit 58578d
struct Idle;
Packit 58578d
struct Active : sc::simple_state< Active, DeferralTest, Idle >
Packit 58578d
{
Packit 58578d
  typedef mpl::list<
Packit 58578d
    sc::custom_reaction< EvLeafDeferred >,
Packit 58578d
    sc::deferral< EvNodeDeferred >,
Packit 58578d
    sc::transition< EvDestroy, Dead >
Packit 58578d
  > reactions;
Packit 58578d
Packit 58578d
  sc::result react( const EvLeafDeferred & )
Packit 58578d
  {
Packit 58578d
    outermost_context().IncrementProcessedCount();
Packit 58578d
    return discard_event();
Packit 58578d
  }
Packit 58578d
};
Packit 58578d
Packit 58578d
  struct Running : sc::simple_state< Running, Active >
Packit 58578d
  {
Packit 58578d
    typedef sc::transition< EvSwitch, Idle > reactions;
Packit 58578d
  };
Packit 58578d
Packit 58578d
  struct Idle : sc::simple_state< Idle, Active >
Packit 58578d
  {
Packit 58578d
    typedef mpl::list<
Packit 58578d
      sc::transition< EvSwitch, Running >,
Packit 58578d
      sc::deferral< EvLeafDeferred >
Packit 58578d
    > reactions;
Packit 58578d
  };
Packit 58578d
Packit 58578d
Packit 58578d
struct EvToX2 : sc::event< EvToX2 > {};
Packit 58578d
struct EvToX3 : sc::event< EvToX3 > {};
Packit 58578d
Packit 58578d
struct X1;
Packit 58578d
struct DeferralEventBaseTest : sc::state_machine< DeferralEventBaseTest, X1 >
Packit 58578d
{
Packit 58578d
};
Packit 58578d
Packit 58578d
struct X3 : sc::simple_state< X3, DeferralEventBaseTest > {};
Packit 58578d
Packit 58578d
struct X2 : sc::simple_state< X2, DeferralEventBaseTest >
Packit 58578d
{
Packit 58578d
  typedef sc::transition< EvToX3, X3 > reactions;
Packit 58578d
};
Packit 58578d
Packit 58578d
struct X1 : sc::simple_state< X1, DeferralEventBaseTest >
Packit 58578d
{
Packit 58578d
  typedef mpl::list<
Packit 58578d
    sc::transition< EvToX2, X2 >,
Packit 58578d
    sc::deferral< sc::event_base >
Packit 58578d
  > reactions;
Packit 58578d
};
Packit 58578d
Packit 58578d
Packit 58578d
int test_main( int, char* [] )
Packit 58578d
{
Packit 58578d
  DeferralTest machine;
Packit 58578d
  machine.initiate();
Packit 58578d
  machine.process_event( *MakeIntrusive( new EvSwitch() ) );
Packit 58578d
  BOOST_REQUIRE( machine.ProcessedCount() == 0 );
Packit 58578d
  machine.process_event( *MakeIntrusive( new EvSwitch() ) );
Packit 58578d
  BOOST_REQUIRE( machine.ProcessedCount() == 0 );
Packit 58578d
  machine.process_event( *MakeIntrusive( new EvLeafDeferred() ) );
Packit 58578d
  BOOST_REQUIRE( machine.ProcessedCount() == 0 );
Packit 58578d
  machine.process_event( *MakeIntrusive( new EvSwitch() ) );
Packit 58578d
  BOOST_REQUIRE( machine.ProcessedCount() == 1 );
Packit 58578d
  machine.process_event( *MakeIntrusive( new EvSwitch() ) );
Packit 58578d
  BOOST_REQUIRE( machine.ProcessedCount() == 1 );
Packit 58578d
  machine.process_event( *MakeIntrusive( new EvLeafDeferred() ) );
Packit 58578d
  machine.process_event( *MakeIntrusive( new EvLeafDeferred() ) );
Packit 58578d
  BOOST_REQUIRE( machine.ProcessedCount() == 1 );
Packit 58578d
  machine.process_event( *MakeIntrusive( new EvSwitch() ) );
Packit 58578d
  BOOST_REQUIRE( machine.ProcessedCount() == 3 );
Packit 58578d
  machine.process_event( *MakeIntrusive( new EvSwitch() ) );
Packit 58578d
  BOOST_REQUIRE( machine.ProcessedCount() == 3 );
Packit 58578d
  machine.process_event( *MakeIntrusive( new EvNodeDeferred() ) );
Packit 58578d
  BOOST_REQUIRE( machine.ProcessedCount() == 3 );
Packit 58578d
  machine.process_event( *MakeIntrusive( new EvSwitch() ) );
Packit 58578d
  BOOST_REQUIRE( machine.ProcessedCount() == 3 );
Packit 58578d
  machine.process_event( EvNodeDeferred() );
Packit 58578d
  BOOST_REQUIRE( machine.ProcessedCount() == 3 );
Packit 58578d
  machine.process_event( *MakeIntrusive( new EvDestroy() ) );
Packit 58578d
  BOOST_REQUIRE( machine.ProcessedCount() == 5 );
Packit 58578d
Packit 58578d
Packit 58578d
  DeferralEventBaseTest eventBaseMachine;
Packit 58578d
  // state_cast sanity check
Packit 58578d
  BOOST_REQUIRE_THROW( eventBaseMachine.state_cast< const X1 & >(), std::bad_cast );
Packit 58578d
  eventBaseMachine.initiate();
Packit 58578d
  BOOST_REQUIRE_NO_THROW( eventBaseMachine.state_cast< const X1 & >() );
Packit 58578d
  // Deferral must work with heap-allocated and stack-allocated events
Packit 58578d
  eventBaseMachine.process_event( EvToX3() );
Packit 58578d
  BOOST_REQUIRE_NO_THROW( eventBaseMachine.state_cast< const X1 & >() );
Packit 58578d
  eventBaseMachine.process_event( EvToX2() );
Packit 58578d
  BOOST_REQUIRE_NO_THROW( eventBaseMachine.state_cast< const X3 & >() );
Packit 58578d
  eventBaseMachine.initiate();
Packit 58578d
  BOOST_REQUIRE_NO_THROW( eventBaseMachine.state_cast< const X1 & >() );
Packit 58578d
  eventBaseMachine.process_event( EvToX2() );
Packit 58578d
  BOOST_REQUIRE_NO_THROW( eventBaseMachine.state_cast< const X2 & >() );
Packit 58578d
Packit 58578d
  return 0;
Packit 58578d
}