1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151
|
// 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 <iostream>
#ifndef BOOST_MSM_NONSTANDALONE_TEST
#define BOOST_TEST_MODULE transition_skipping_test
#endif
#include <boost/test/unit_test.hpp>
#include <boost/core/demangle.hpp>
#include "BackCommon.hpp"
// front-end
#include <boost/fusion/include/insert_range.hpp>
#include <boost/msm/front/euml/operator.hpp>
#include <boost/msm/front/functor_row.hpp>
#include <boost/msm/front/state_machine_def.hpp>
template <typename ...T>
using msm_flags = boost::mpl::vector<T...>;
template <typename ...T>
using msm_transition_table = boost::mpl::vector<T...>;
namespace msmf = boost::msm::front;
namespace euml = boost::msm::front::euml;
struct evt1 {};
struct evt2 {};
struct evt3 {};
struct top_ : public msmf::state_machine_def<top_> {
int count_guard_false = 0;
int count_guard_true = 0;
struct nested : public msmf::state<> {
template <class Event, class FSM>
void on_entry(Event const&, FSM&) { ++entry_counter; }
template <class Event, class FSM>
void on_exit(Event const&, FSM&) { ++exit_counter; }
int entry_counter=0;
int exit_counter=0;
};
struct other1 : public msmf::state<> {
template <class Event, class FSM>
void on_entry(Event const&, FSM&) { ++entry_counter; }
template <class Event, class FSM>
void on_exit(Event const&, FSM&) { ++exit_counter; }
int entry_counter = 0;
int exit_counter = 0;
};
struct other2 : public msmf::state<> {
template <class Event, class FSM>
void on_entry(Event const&, FSM&) { ++entry_counter; }
template <class Event, class FSM>
void on_exit(Event const&, FSM&) { ++exit_counter; }
int entry_counter = 0;
int exit_counter = 0;
};
struct other3 : public msmf::state<> {
template <class Event, class FSM>
void on_entry(Event const&, FSM&) { ++entry_counter; }
template <class Event, class FSM>
void on_exit(Event const&, FSM&) { ++exit_counter; }
int entry_counter = 0;
int exit_counter = 0;
};
struct other4 : public msmf::state<> {
template <class Event, class FSM>
void on_entry(Event const&, FSM&) { ++entry_counter; }
template <class Event, class FSM>
void on_exit(Event const&, FSM&) { ++exit_counter; }
int entry_counter = 0;
int exit_counter = 0;
};
struct other5 : public msmf::state<> {
template <class Event, class FSM>
void on_entry(Event const&, FSM&) { ++entry_counter; }
template <class Event, class FSM>
void on_exit(Event const&, FSM&) { ++exit_counter; }
int entry_counter = 0;
int exit_counter = 0;
};
struct guard_true {
template <class EVT, class FSM, class SourceState, class TargetState>
bool operator()(EVT const&, FSM& fsm, SourceState&, TargetState&) const {
++fsm.count_guard_true;
return true;
}
};
struct guard_false {
template <class EVT, class FSM, class SourceState, class TargetState>
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<top_>;
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<top_::nested&>().exit_counter == 1, "nested exit not called correctly");
BOOST_CHECK_MESSAGE(msm.template get_state<top_::nested&>().entry_counter == 1, "nested entry not called correctly");
BOOST_CHECK_MESSAGE(msm.template get_state<top_::other2&>().exit_counter == 0, "other2 exit not called correctly");
BOOST_CHECK_MESSAGE(msm.template get_state<top_::other2&>().entry_counter == 1, "other2 entry not called correctly");
BOOST_CHECK_MESSAGE(msm.template get_state<top_::other1&>().exit_counter == 0, "other1 exit not called correctly");
BOOST_CHECK_MESSAGE(msm.template get_state<top_::other1&>().entry_counter == 0, "other1 entry not called correctly");
BOOST_CHECK_MESSAGE(msm.template get_state<top_::other3&>().exit_counter == 0, "other3 exit not called correctly");
BOOST_CHECK_MESSAGE(msm.template get_state<top_::other3&>().entry_counter == 0, "other3 entry not called correctly");
BOOST_CHECK_MESSAGE(msm.template get_state<top_::other4&>().exit_counter == 0, "other4 exit not called correctly");
BOOST_CHECK_MESSAGE(msm.template get_state<top_::other4&>().entry_counter == 0, "other4 entry not called correctly");
BOOST_CHECK_MESSAGE(msm.current_state()[0] == 2, "other2 should be active"); //Open
}
|