// Copyright 2010 Christophe Henry // henry UNDERSCORE christophe AT hotmail DOT com // This is an extended version of the state machine available in the boost::mpl library // Distributed under the same license as the original. // Copyright for the original version: // Copyright 2005 David Abrahams and Aleksey Gurtovoy. Distributed // under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #include #ifndef BOOST_MSM_NONSTANDALONE_TEST #define BOOST_TEST_MODULE transition_skipping_test #endif #include #include #include "BackCommon.hpp" // front-end #include #include #include #include template using msm_flags = boost::mpl::vector; template using msm_transition_table = boost::mpl::vector; namespace msmf = boost::msm::front; namespace euml = boost::msm::front::euml; struct evt1 {}; struct evt2 {}; struct evt3 {}; struct top_ : public msmf::state_machine_def { int count_guard_false = 0; int count_guard_true = 0; struct nested : public msmf::state<> { template void on_entry(Event const&, FSM&) { ++entry_counter; } template void on_exit(Event const&, FSM&) { ++exit_counter; } int entry_counter=0; int exit_counter=0; }; struct other1 : public msmf::state<> { template void on_entry(Event const&, FSM&) { ++entry_counter; } template void on_exit(Event const&, FSM&) { ++exit_counter; } int entry_counter = 0; int exit_counter = 0; }; struct other2 : public msmf::state<> { template void on_entry(Event const&, FSM&) { ++entry_counter; } template void on_exit(Event const&, FSM&) { ++exit_counter; } int entry_counter = 0; int exit_counter = 0; }; struct other3 : public msmf::state<> { template void on_entry(Event const&, FSM&) { ++entry_counter; } template void on_exit(Event const&, FSM&) { ++exit_counter; } int entry_counter = 0; int exit_counter = 0; }; struct other4 : public msmf::state<> { template void on_entry(Event const&, FSM&) { ++entry_counter; } template void on_exit(Event const&, FSM&) { ++exit_counter; } int entry_counter = 0; int exit_counter = 0; }; struct other5 : public msmf::state<> { template void on_entry(Event const&, FSM&) { ++entry_counter; } template void on_exit(Event const&, FSM&) { ++exit_counter; } int entry_counter = 0; int exit_counter = 0; }; struct guard_true { template bool operator()(EVT const&, FSM& fsm, SourceState&, TargetState&) const { ++fsm.count_guard_true; return true; } }; struct guard_false { template bool operator()(EVT const&, FSM& fsm, SourceState&, TargetState&) const { ++fsm.count_guard_false; return false; } }; typedef nested initial_state; using transition_table = msm_transition_table< // Start Event Next Action Guard //--------+------------+---------+------------+-----------+-------------- msmf::Row < nested, msmf::none, other1, msmf::none, guard_false>, msmf::Row < nested, msmf::none, other2, msmf::none, guard_true >, // <- this transition is not executed with back11 msmf::Row < nested, msmf::none, other3, msmf::none, guard_false>, msmf::Row < nested, msmf::none, other4, msmf::none, guard_false>, msmf::Row < other1, evt3, nested, msmf::none, msmf::none > >; }; using tops = get_test_machines; BOOST_AUTO_TEST_CASE_TEMPLATE(transition_skipping_test, top, tops) { top msm; msm.start(); BOOST_CHECK_MESSAGE(msm.count_guard_true == 1, "guard_true should be called once"); BOOST_CHECK_MESSAGE(msm.count_guard_false == 2, "guard_false should be called once"); BOOST_CHECK_MESSAGE(msm.template get_state().exit_counter == 1, "nested exit not called correctly"); BOOST_CHECK_MESSAGE(msm.template get_state().entry_counter == 1, "nested entry not called correctly"); BOOST_CHECK_MESSAGE(msm.template get_state().exit_counter == 0, "other2 exit not called correctly"); BOOST_CHECK_MESSAGE(msm.template get_state().entry_counter == 1, "other2 entry not called correctly"); BOOST_CHECK_MESSAGE(msm.template get_state().exit_counter == 0, "other1 exit not called correctly"); BOOST_CHECK_MESSAGE(msm.template get_state().entry_counter == 0, "other1 entry not called correctly"); BOOST_CHECK_MESSAGE(msm.template get_state().exit_counter == 0, "other3 exit not called correctly"); BOOST_CHECK_MESSAGE(msm.template get_state().entry_counter == 0, "other3 entry not called correctly"); BOOST_CHECK_MESSAGE(msm.template get_state().exit_counter == 0, "other4 exit not called correctly"); BOOST_CHECK_MESSAGE(msm.template get_state().entry_counter == 0, "other4 entry not called correctly"); BOOST_CHECK_MESSAGE(msm.current_state()[0] == 2, "other2 should be active"); //Open }