123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334 |
- //////////////////////////////////////////////////////////////////////////////
- // 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/simple_state.hpp>
- #include <boost/statechart/event.hpp>
- #include <boost/statechart/transition.hpp>
- #include <boost/statechart/shallow_history.hpp>
- #include <boost/statechart/deep_history.hpp>
- #include <boost/mpl/list.hpp>
- #include <boost/shared_ptr.hpp>
- #include <boost/test/test_tools.hpp>
- #include <stdexcept>
- namespace sc = boost::statechart;
- namespace mpl = boost::mpl;
- struct EvToB : sc::event< EvToB > {};
- struct EvToD : sc::event< EvToD > {};
- struct EvToDShallow : sc::event< EvToDShallow > {};
- struct EvToDDeep : sc::event< EvToDDeep > {};
- struct EvToDShallowLocal : sc::event< EvToDShallowLocal > {};
- struct EvToDDeepLocal : sc::event< EvToDDeepLocal > {};
- struct EvToF : sc::event< EvToF > {};
- struct EvToFShallow : sc::event< EvToFShallow > {};
- struct EvToFDeep : sc::event< EvToFDeep > {};
- struct EvToH : sc::event< EvToH > {};
- struct EvToI : sc::event< EvToI > {};
- struct EvToM : sc::event< EvToM > {};
- struct EvToQ : sc::event< EvToQ > {};
- struct EvWhatever : sc::event< EvWhatever > {};
- struct A;
- struct HistoryTest : sc::state_machine< HistoryTest, A >
- {
- void unconsumed_event( const sc::event_base & )
- {
- throw std::runtime_error( "Event was not consumed!" );
- }
- };
- struct B;
- struct D;
- struct F;
- struct H;
- struct I;
- struct M;
- struct Q;
- struct A : sc::simple_state< A, HistoryTest, B >
- {
- typedef mpl::list<
- sc::transition< EvToB, B >,
- sc::transition< EvToD, D >,
- sc::transition< EvToDShallow, sc::shallow_history< D > >,
- sc::transition< EvToDDeep, sc::deep_history< D > >,
- sc::transition< EvToF, F >,
- sc::transition< EvToFShallow, sc::shallow_history< F > >,
- sc::transition< EvToFDeep, sc::deep_history< F > >,
- sc::transition< EvToH, H >,
- sc::transition< EvToI, I >,
- sc::transition< EvToM, M >,
- sc::transition< EvToQ, Q >
- > reactions;
- };
- struct J;
- struct N;
- struct B : sc::simple_state<
- B, A, mpl::list< sc::shallow_history< J >, sc::deep_history< N > >,
- sc::has_full_history > {};
- struct J : sc::simple_state< J, B::orthogonal< 0 > > {};
- struct L;
- struct K : sc::simple_state< K, B::orthogonal< 0 >, L > {};
- struct L : sc::simple_state< L, K > {};
- struct M : sc::simple_state< M, K > {};
- struct N : sc::simple_state< N, B::orthogonal< 1 > > {};
- struct P;
- struct O : sc::simple_state< O, B::orthogonal< 1 >, P > {};
- struct P : sc::simple_state< P, O > {};
- struct Q : sc::simple_state< Q, O > {};
- struct C : sc::simple_state< C, A, D, sc::has_full_history > {};
- struct D : sc::simple_state< D, C > {};
- struct E : sc::simple_state< E, C, F, sc::has_full_history > {};
- struct F : sc::simple_state< F, E > {};
- struct G : sc::simple_state< G, E, H >
- {
- typedef mpl::list<
- sc::transition< EvToDShallowLocal, sc::shallow_history< D > >,
- sc::transition< EvToDDeepLocal, sc::deep_history< D > >
- > reactions;
- };
- struct H : sc::simple_state< H, G > {};
- struct I : sc::simple_state< I, G > {};
- int test_main( int, char* [] )
- {
- boost::shared_ptr< HistoryTest > pM =
- boost::shared_ptr< HistoryTest >( new HistoryTest() );
- // state_downcast sanity check
- BOOST_REQUIRE_THROW( pM->state_downcast< const B & >(), std::bad_cast );
- pM->initiate();
- BOOST_REQUIRE_THROW( pM->state_downcast< const D & >(), std::bad_cast );
- BOOST_REQUIRE_NO_THROW( pM->state_downcast< const B & >() );
- // No history has been saved yet -> default state
- pM->process_event( EvToDShallow() );
- BOOST_REQUIRE_NO_THROW( pM->state_downcast< const D & >() );
- pM->process_event( EvToDShallow() );
- BOOST_REQUIRE_NO_THROW( pM->state_downcast< const D & >() );
- pM->process_event( EvToI() );
- BOOST_REQUIRE_NO_THROW( pM->state_downcast< const I & >() );
- // Direct inner is E when history is saved -> F
- pM->process_event( EvToDShallow() );
- BOOST_REQUIRE_NO_THROW( pM->state_downcast< const F & >() );
- pM->process_event( EvToH() );
- BOOST_REQUIRE_NO_THROW( pM->state_downcast< const H & >() );
- // Direct inner is E when history is saved -> F
- pM->process_event( EvToDShallow() );
- BOOST_REQUIRE_NO_THROW( pM->state_downcast< const F & >() );
- pM->process_event( EvToF() );
- BOOST_REQUIRE_NO_THROW( pM->state_downcast< const F & >() );
- pM->process_event( EvToB() );
- BOOST_REQUIRE_NO_THROW( pM->state_downcast< const B & >() );
- // Direct inner was E when history was saved -> F
- pM->process_event( EvToDShallow() );
- BOOST_REQUIRE_NO_THROW( pM->state_downcast< const F & >() );
- pM->initiate();
- // History was cleared in termination -> default state
- pM->process_event( EvToDShallow() );
- BOOST_REQUIRE_NO_THROW( pM->state_downcast< const D & >() );
- pM->process_event( EvToI() );
- BOOST_REQUIRE_NO_THROW( pM->state_downcast< const I & >() );
- pM->process_event( EvToB() );
- BOOST_REQUIRE_NO_THROW( pM->state_downcast< const B & >() );
- pM->clear_shallow_history< C, 0 >();
- // History was cleared -> default state
- pM->process_event( EvToDShallow() );
- BOOST_REQUIRE_NO_THROW( pM->state_downcast< const D & >() );
- pM = boost::shared_ptr< HistoryTest >( new HistoryTest() );
- pM->initiate();
- BOOST_REQUIRE_NO_THROW( pM->state_downcast< const B & >() );
- // No history has been saved yet -> default state
- pM->process_event( EvToDDeep() );
- BOOST_REQUIRE_NO_THROW( pM->state_downcast< const D & >() );
- pM->process_event( EvToDDeep() );
- BOOST_REQUIRE_NO_THROW( pM->state_downcast< const D & >() );
- pM->process_event( EvToI() );
- BOOST_REQUIRE_NO_THROW( pM->state_downcast< const I & >() );
- pM->process_event( EvToB() );
- BOOST_REQUIRE_NO_THROW( pM->state_downcast< const B & >() );
- pM->process_event( EvToDDeep() );
- BOOST_REQUIRE_NO_THROW( pM->state_downcast< const I & >() );
- pM->process_event( EvToH() );
- BOOST_REQUIRE_NO_THROW( pM->state_downcast< const H & >() );
- pM->process_event( EvToB() );
- BOOST_REQUIRE_NO_THROW( pM->state_downcast< const B & >() );
- pM->process_event( EvToDDeep() );
- BOOST_REQUIRE_NO_THROW( pM->state_downcast< const H & >() );
- pM->process_event( EvToF() );
- BOOST_REQUIRE_NO_THROW( pM->state_downcast< const F & >() );
- pM->process_event( EvToB() );
- BOOST_REQUIRE_NO_THROW( pM->state_downcast< const B & >() );
- pM->process_event( EvToDDeep() );
- BOOST_REQUIRE_NO_THROW( pM->state_downcast< const F & >() );
- pM->initiate();
- // History was cleared in termination -> default state
- pM->process_event( EvToDDeep() );
- BOOST_REQUIRE_NO_THROW( pM->state_downcast< const D & >() );
- pM->process_event( EvToI() );
- BOOST_REQUIRE_NO_THROW( pM->state_downcast< const I & >() );
- pM->process_event( EvToB() );
- BOOST_REQUIRE_NO_THROW( pM->state_downcast< const B & >() );
- pM->clear_deep_history< C, 0 >();
- // History was cleared -> default state
- pM->process_event( EvToDDeep() );
- BOOST_REQUIRE_NO_THROW( pM->state_downcast< const D & >() );
- pM = boost::shared_ptr< HistoryTest >( new HistoryTest() );
- pM->initiate();
- BOOST_REQUIRE_NO_THROW( pM->state_downcast< const B & >() );
- // No history has been saved yet -> default state
- pM->process_event( EvToFShallow() );
- BOOST_REQUIRE_NO_THROW( pM->state_downcast< const F & >() );
- pM->process_event( EvToFShallow() );
- BOOST_REQUIRE_NO_THROW( pM->state_downcast< const F & >() );
- pM->process_event( EvToI() );
- BOOST_REQUIRE_NO_THROW( pM->state_downcast< const I & >() );
- // Direct inner is G when history is saved -> H
- pM->process_event( EvToFShallow() );
- BOOST_REQUIRE_NO_THROW( pM->state_downcast< const H & >() );
- pM->process_event( EvToH() );
- BOOST_REQUIRE_NO_THROW( pM->state_downcast< const H & >() );
- pM->process_event( EvToB() );
- BOOST_REQUIRE_NO_THROW( pM->state_downcast< const B & >() );
- // Direct inner was G when history was saved -> H
- pM->process_event( EvToFShallow() );
- BOOST_REQUIRE_NO_THROW( pM->state_downcast< const H & >() );
- pM->process_event( EvToI() );
- BOOST_REQUIRE_NO_THROW( pM->state_downcast< const I & >() );
- pM->initiate();
- // History was cleared in termination -> default state
- pM->process_event( EvToFShallow() );
- BOOST_REQUIRE_NO_THROW( pM->state_downcast< const F & >() );
- pM->process_event( EvToI() );
- BOOST_REQUIRE_NO_THROW( pM->state_downcast< const I & >() );
- pM->process_event( EvToB() );
- BOOST_REQUIRE_NO_THROW( pM->state_downcast< const B & >() );
- pM->clear_shallow_history< E, 0 >();
- // History was cleared -> default state
- pM->process_event( EvToFShallow() );
- BOOST_REQUIRE_NO_THROW( pM->state_downcast< const F & >() );
- pM = boost::shared_ptr< HistoryTest >( new HistoryTest() );
- pM->initiate();
- BOOST_REQUIRE_NO_THROW( pM->state_downcast< const B & >() );
- // No history has been saved yet -> default state
- pM->process_event( EvToFDeep() );
- BOOST_REQUIRE_NO_THROW( pM->state_downcast< const F & >() );
- pM->process_event( EvToFDeep() );
- BOOST_REQUIRE_NO_THROW( pM->state_downcast< const F & >() );
- pM->process_event( EvToI() );
- BOOST_REQUIRE_NO_THROW( pM->state_downcast< const I & >() );
- pM->process_event( EvToB() );
- BOOST_REQUIRE_NO_THROW( pM->state_downcast< const B & >() );
- pM->process_event( EvToFDeep() );
- BOOST_REQUIRE_NO_THROW( pM->state_downcast< const I & >() );
- pM->process_event( EvToH() );
- BOOST_REQUIRE_NO_THROW( pM->state_downcast< const H & >() );
- pM->process_event( EvToB() );
- BOOST_REQUIRE_NO_THROW( pM->state_downcast< const B & >() );
- pM->process_event( EvToFDeep() );
- BOOST_REQUIRE_NO_THROW( pM->state_downcast< const H & >() );
- pM->process_event( EvToF() );
- BOOST_REQUIRE_NO_THROW( pM->state_downcast< const F & >() );
- pM->process_event( EvToB() );
- BOOST_REQUIRE_NO_THROW( pM->state_downcast< const B & >() );
- pM->process_event( EvToFDeep() );
- BOOST_REQUIRE_NO_THROW( pM->state_downcast< const F & >() );
- pM->initiate();
- // History was cleared in termination -> default state
- pM->process_event( EvToFDeep() );
- BOOST_REQUIRE_NO_THROW( pM->state_downcast< const F & >() );
- pM->process_event( EvToI() );
- BOOST_REQUIRE_NO_THROW( pM->state_downcast< const I & >() );
- pM->process_event( EvToB() );
- BOOST_REQUIRE_NO_THROW( pM->state_downcast< const B & >() );
- pM->clear_deep_history< E, 0 >();
- // History was cleared -> default state
- pM->process_event( EvToFDeep() );
- BOOST_REQUIRE_NO_THROW( pM->state_downcast< const F & >() );
- // Test local history (new with UML 2.0)
- pM->initiate();
- // unconsumed_event sanity check
- BOOST_REQUIRE_THROW( pM->process_event( EvWhatever() ), std::runtime_error );
- pM->process_event( EvToI() );
- BOOST_REQUIRE_NO_THROW( pM->state_downcast< const I & >() );
- pM->process_event( EvToDShallowLocal() );
- BOOST_REQUIRE_NO_THROW( pM->state_downcast< const F & >() );
- pM->process_event( EvToI() );
- pM->process_event( EvToDDeepLocal() );
- BOOST_REQUIRE_NO_THROW( pM->state_downcast< const I & >() );
- // Given that history transitions and history initial states are implemented
- // with the same code we just make a few sanity checks and trust that the
- // rest will work just like we tested above.
- pM->process_event( EvToB() );
- BOOST_REQUIRE_NO_THROW( pM->state_downcast< const J & >() );
- BOOST_REQUIRE_NO_THROW( pM->state_downcast< const N & >() );
- pM->process_event( EvToM() );
- BOOST_REQUIRE_NO_THROW( pM->state_downcast< const M & >() );
- // Direct inner is K when history is saved -> L
- pM->process_event( EvToB() );
- BOOST_REQUIRE_NO_THROW( pM->state_downcast< const L & >() );
- BOOST_REQUIRE_NO_THROW( pM->state_downcast< const N & >() );
- pM->process_event( EvToQ() );
- BOOST_REQUIRE_NO_THROW( pM->state_downcast< const Q & >() );
- pM->process_event( EvToB() );
- BOOST_REQUIRE_NO_THROW( pM->state_downcast< const Q & >() );
- return 0;
- }
|