Refactor tests (#2)

* Extracted traits into a separate header to include multiple backends at once
* Refactored tests to test multiple variations of backends with the same test code
* Added test cases with back::favor_compile_time for existing tests
* Removed redundant Back11 tests
This commit is contained in:
Christian Granzin
2025-03-09 16:27:05 +01:00
committed by GitHub
parent 33e77cbfc7
commit 7753fa0170
62 changed files with 1509 additions and 4441 deletions
+1 -2
View File
@@ -25,11 +25,10 @@
#include <boost/type_traits/is_same.hpp>
#include <boost/msm/event_traits.hpp>
#include <boost/msm/back/traits.hpp>
#include <boost/msm/back/metafunctions.hpp>
#include <boost/msm/back/common_types.hpp>
BOOST_MPL_HAS_XXX_TRAIT_DEF(is_frow)
namespace boost { namespace msm { namespace back
{
+1 -14
View File
@@ -57,20 +57,7 @@
#include <boost/msm/mpl_graph/incidence_list_graph.hpp>
#include <boost/msm/mpl_graph/depth_first_search.hpp>
BOOST_MPL_HAS_XXX_TRAIT_DEF(explicit_creation)
BOOST_MPL_HAS_XXX_TRAIT_DEF(pseudo_entry)
BOOST_MPL_HAS_XXX_TRAIT_DEF(pseudo_exit)
BOOST_MPL_HAS_XXX_TRAIT_DEF(concrete_exit_state)
BOOST_MPL_HAS_XXX_TRAIT_DEF(composite_tag)
BOOST_MPL_HAS_XXX_TRAIT_DEF(not_real_row_tag)
BOOST_MPL_HAS_XXX_TRAIT_DEF(event_blocking_flag)
BOOST_MPL_HAS_XXX_TRAIT_DEF(explicit_entry_state)
BOOST_MPL_HAS_XXX_TRAIT_DEF(completion_event)
BOOST_MPL_HAS_XXX_TRAIT_DEF(no_exception_thrown)
BOOST_MPL_HAS_XXX_TRAIT_DEF(no_message_queue)
BOOST_MPL_HAS_XXX_TRAIT_DEF(activate_deferred_events)
BOOST_MPL_HAS_XXX_TRAIT_DEF(wrapped_entry)
BOOST_MPL_HAS_XXX_TRAIT_DEF(active_state_switch_policy)
#include <boost/msm/back/traits.hpp>
namespace boost { namespace msm { namespace back
{
+1 -14
View File
@@ -56,6 +56,7 @@
#include <boost/msm/active_state_switching_policies.hpp>
#include <boost/msm/row_tags.hpp>
#include <boost/msm/msm_grammar.hpp>
#include <boost/msm/back/traits.hpp>
#include <boost/msm/back/fold_to_list.hpp>
#include <boost/msm/back/metafunctions.hpp>
#include <boost/msm/back/history_policies.hpp>
@@ -66,20 +67,6 @@
#include <boost/msm/back/no_fsm_check.hpp>
#include <boost/msm/back/queue_container_deque.hpp>
BOOST_MPL_HAS_XXX_TRAIT_DEF(accept_sig)
BOOST_MPL_HAS_XXX_TRAIT_DEF(no_automatic_create)
BOOST_MPL_HAS_XXX_TRAIT_DEF(non_forwarding_flag)
BOOST_MPL_HAS_XXX_TRAIT_DEF(direct_entry)
BOOST_MPL_HAS_XXX_TRAIT_DEF(initial_event)
BOOST_MPL_HAS_XXX_TRAIT_DEF(final_event)
BOOST_MPL_HAS_XXX_TRAIT_DEF(do_serialize)
BOOST_MPL_HAS_XXX_TRAIT_DEF(history_policy)
BOOST_MPL_HAS_XXX_TRAIT_DEF(fsm_check)
BOOST_MPL_HAS_XXX_TRAIT_DEF(compile_policy)
BOOST_MPL_HAS_XXX_TRAIT_DEF(queue_container_policy)
BOOST_MPL_HAS_XXX_TRAIT_DEF(using_declared_table)
BOOST_MPL_HAS_XXX_TRAIT_DEF(event_queue_before_deferred_queue)
#ifndef BOOST_MSM_CONSTRUCTOR_ARG_SIZE
#define BOOST_MSM_CONSTRUCTOR_ARG_SIZE 5 // default max number of arguments for constructors
#endif
+50
View File
@@ -0,0 +1,50 @@
// Copyright 2008 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)
#ifndef BOOST_MSM_BACK_TRAITS_H
#define BOOST_MSM_BACK_TRAITS_H
#include <boost/mpl/has_xxx.hpp>
// Metafunctions
BOOST_MPL_HAS_XXX_TRAIT_DEF(explicit_creation)
BOOST_MPL_HAS_XXX_TRAIT_DEF(pseudo_entry)
BOOST_MPL_HAS_XXX_TRAIT_DEF(pseudo_exit)
BOOST_MPL_HAS_XXX_TRAIT_DEF(concrete_exit_state)
BOOST_MPL_HAS_XXX_TRAIT_DEF(composite_tag)
BOOST_MPL_HAS_XXX_TRAIT_DEF(not_real_row_tag)
BOOST_MPL_HAS_XXX_TRAIT_DEF(event_blocking_flag)
BOOST_MPL_HAS_XXX_TRAIT_DEF(explicit_entry_state)
BOOST_MPL_HAS_XXX_TRAIT_DEF(completion_event)
BOOST_MPL_HAS_XXX_TRAIT_DEF(no_exception_thrown)
BOOST_MPL_HAS_XXX_TRAIT_DEF(no_message_queue)
BOOST_MPL_HAS_XXX_TRAIT_DEF(activate_deferred_events)
BOOST_MPL_HAS_XXX_TRAIT_DEF(wrapped_entry)
BOOST_MPL_HAS_XXX_TRAIT_DEF(active_state_switch_policy)
// State machine
BOOST_MPL_HAS_XXX_TRAIT_DEF(accept_sig)
BOOST_MPL_HAS_XXX_TRAIT_DEF(no_automatic_create)
BOOST_MPL_HAS_XXX_TRAIT_DEF(non_forwarding_flag)
BOOST_MPL_HAS_XXX_TRAIT_DEF(direct_entry)
BOOST_MPL_HAS_XXX_TRAIT_DEF(initial_event)
BOOST_MPL_HAS_XXX_TRAIT_DEF(final_event)
BOOST_MPL_HAS_XXX_TRAIT_DEF(do_serialize)
BOOST_MPL_HAS_XXX_TRAIT_DEF(history_policy)
BOOST_MPL_HAS_XXX_TRAIT_DEF(fsm_check)
BOOST_MPL_HAS_XXX_TRAIT_DEF(compile_policy)
BOOST_MPL_HAS_XXX_TRAIT_DEF(queue_container_policy)
BOOST_MPL_HAS_XXX_TRAIT_DEF(using_declared_table)
BOOST_MPL_HAS_XXX_TRAIT_DEF(event_queue_before_deferred_queue)
// Dispatch table
BOOST_MPL_HAS_XXX_TRAIT_DEF(is_frow)
#endif // BOOST_MSM_BACK_TRAITS_H
+1 -2
View File
@@ -31,11 +31,10 @@
#include <boost/type_traits/is_same.hpp>
#include <boost/msm/event_traits.hpp>
#include <boost/msm/back/traits.hpp>
#include <boost/msm/back11/metafunctions.hpp>
#include <boost/msm/back/common_types.hpp>
BOOST_MPL_HAS_XXX_TRAIT_DEF(is_frow)
namespace boost { namespace msm { namespace back11
{
+1 -14
View File
@@ -69,20 +69,7 @@
#include <boost/msm/mpl_graph/incidence_list_graph.hpp>
#include <boost/msm/mpl_graph/depth_first_search.hpp>
BOOST_MPL_HAS_XXX_TRAIT_DEF(explicit_creation)
BOOST_MPL_HAS_XXX_TRAIT_DEF(pseudo_entry)
BOOST_MPL_HAS_XXX_TRAIT_DEF(pseudo_exit)
BOOST_MPL_HAS_XXX_TRAIT_DEF(concrete_exit_state)
BOOST_MPL_HAS_XXX_TRAIT_DEF(composite_tag)
BOOST_MPL_HAS_XXX_TRAIT_DEF(not_real_row_tag)
BOOST_MPL_HAS_XXX_TRAIT_DEF(event_blocking_flag)
BOOST_MPL_HAS_XXX_TRAIT_DEF(explicit_entry_state)
BOOST_MPL_HAS_XXX_TRAIT_DEF(completion_event)
BOOST_MPL_HAS_XXX_TRAIT_DEF(no_exception_thrown)
BOOST_MPL_HAS_XXX_TRAIT_DEF(no_message_queue)
BOOST_MPL_HAS_XXX_TRAIT_DEF(activate_deferred_events)
BOOST_MPL_HAS_XXX_TRAIT_DEF(wrapped_entry)
BOOST_MPL_HAS_XXX_TRAIT_DEF(active_state_switch_policy)
#include <boost/msm/back/traits.hpp>
namespace boost { namespace msm { namespace back11
{
+5 -18
View File
@@ -59,6 +59,7 @@
#include <boost/msm/active_state_switching_policies.hpp>
#include <boost/msm/row_tags.hpp>
#include <boost/msm/msm_grammar.hpp>
#include <boost/msm/back/traits.hpp>
#include <boost/msm/back/fold_to_list.hpp>
#include <boost/msm/back11/metafunctions.hpp>
#include <boost/msm/back/history_policies.hpp>
@@ -69,20 +70,6 @@
#include <boost/msm/back/queue_container_deque.hpp>
#include <boost/msm/back11/dispatch_table.hpp>
BOOST_MPL_HAS_XXX_TRAIT_DEF(accept_sig)
BOOST_MPL_HAS_XXX_TRAIT_DEF(no_automatic_create)
BOOST_MPL_HAS_XXX_TRAIT_DEF(non_forwarding_flag)
BOOST_MPL_HAS_XXX_TRAIT_DEF(direct_entry)
BOOST_MPL_HAS_XXX_TRAIT_DEF(initial_event)
BOOST_MPL_HAS_XXX_TRAIT_DEF(final_event)
BOOST_MPL_HAS_XXX_TRAIT_DEF(do_serialize)
BOOST_MPL_HAS_XXX_TRAIT_DEF(history_policy)
BOOST_MPL_HAS_XXX_TRAIT_DEF(fsm_check)
BOOST_MPL_HAS_XXX_TRAIT_DEF(compile_policy)
BOOST_MPL_HAS_XXX_TRAIT_DEF(queue_container_policy)
BOOST_MPL_HAS_XXX_TRAIT_DEF(using_declared_table)
BOOST_MPL_HAS_XXX_TRAIT_DEF(event_queue_before_deferred_queue)
#ifndef BOOST_MSM_CONSTRUCTOR_ARG_SIZE
#define BOOST_MSM_CONSTRUCTOR_ARG_SIZE 5 // default max number of arguments for constructors
#endif
@@ -449,7 +436,7 @@ private:
BOOST_ASSERT(state == (current_state));
// if T1 is an exit pseudo state, then take the transition only if the pseudo exit state is active
if (has_pseudo_exit<T1>::type::value &&
!is_exit_state_active<T1,get_owner<T1,library_sm> >(fsm))
!back11::is_exit_state_active<T1,get_owner<T1,library_sm> >(fsm))
{
return ::boost::msm::back::HANDLED_FALSE;
}
@@ -530,7 +517,7 @@ private:
// if T1 is an exit pseudo state, then take the transition only if the pseudo exit state is active
if (has_pseudo_exit<T1>::type::value &&
!is_exit_state_active<T1,get_owner<T1,library_sm> >(fsm))
!back11::is_exit_state_active<T1,get_owner<T1,library_sm> >(fsm))
{
return ::boost::msm::back::HANDLED_FALSE;
}
@@ -595,7 +582,7 @@ private:
// if T1 is an exit pseudo state, then take the transition only if the pseudo exit state is active
if (has_pseudo_exit<T1>::type::value &&
!is_exit_state_active<T1,get_owner<T1,library_sm> >(fsm))
!back11::is_exit_state_active<T1,get_owner<T1,library_sm> >(fsm))
{
return ::boost::msm::back::HANDLED_FALSE;
}
@@ -662,7 +649,7 @@ private:
// if T1 is an exit pseudo state, then take the transition only if the pseudo exit state is active
if (has_pseudo_exit<T1>::type::value &&
!is_exit_state_active<T1,get_owner<T1,library_sm> >(fsm))
!back11::is_exit_state_active<T1,get_owner<T1,library_sm> >(fsm))
{
return ::boost::msm::back::HANDLED_FALSE;
}
+19 -19
View File
@@ -9,12 +9,12 @@
// http://www.boost.org/LICENSE_1_0.txt)
// back-end
#include <boost/msm/back/state_machine.hpp>
#include "BackCommon.hpp"
//front-end
#include <boost/msm/front/state_machine_def.hpp>
#ifndef BOOST_MSM_NONSTANDALONE_TEST
#define BOOST_TEST_MODULE MyTest
#define BOOST_TEST_MODULE anonymous_test
#endif
#include <boost/test/unit_test.hpp>
@@ -136,12 +136,12 @@ namespace
}
};
// Pick a back-end
typedef msm::back::state_machine<my_machine_> my_machine;
typedef get_test_machines<my_machine_> my_machines;
//static char const* const state_names[] = { "State1", "State2", "State3", "State4" };
BOOST_AUTO_TEST_CASE( anonymous_test )
BOOST_AUTO_TEST_CASE_TEMPLATE ( anonymous_test, my_machine, my_machines )
{
my_machine p;
@@ -149,13 +149,13 @@ namespace
// in this case it will also immediately trigger all anonymous transitions
p.start();
BOOST_CHECK_MESSAGE(p.current_state()[0] == 3,"State4 should be active"); //State4
BOOST_CHECK_MESSAGE(p.get_state<my_machine_::State1&>().exit_counter == 1,"State1 exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<my_machine_::State1&>().entry_counter == 1,"State1 entry not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<my_machine_::State2&>().exit_counter == 1,"State2 exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<my_machine_::State2&>().entry_counter == 1,"State2 entry not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<my_machine_::State3&>().exit_counter == 1,"State3 exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<my_machine_::State3&>().entry_counter == 1,"State3 entry not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<my_machine_::State4&>().entry_counter == 1,"State4 entry not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<my_machine_::State1&>().exit_counter == 1,"State1 exit not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<my_machine_::State1&>().entry_counter == 1,"State1 entry not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<my_machine_::State2&>().exit_counter == 1,"State2 exit not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<my_machine_::State2&>().entry_counter == 1,"State2 entry not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<my_machine_::State3&>().exit_counter == 1,"State3 exit not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<my_machine_::State3&>().entry_counter == 1,"State3 entry not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<my_machine_::State4&>().entry_counter == 1,"State4 entry not called correctly");
BOOST_CHECK_MESSAGE(p.always_true_counter == 1,"guard not called correctly");
BOOST_CHECK_MESSAGE(p.always_false_counter == 1,"guard not called correctly");
BOOST_CHECK_MESSAGE(p.state2_to_state3_counter == 1,"action not called correctly");
@@ -165,14 +165,14 @@ namespace
// this event will bring us back to the initial state and thus, a new "loop" will be started
p.process_event(event1());
BOOST_CHECK_MESSAGE(p.current_state()[0] == 3,"State4 should be active"); //State4
BOOST_CHECK_MESSAGE(p.get_state<my_machine_::State1&>().exit_counter == 2,"State1 exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<my_machine_::State1&>().entry_counter == 2,"State1 entry not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<my_machine_::State2&>().exit_counter == 2,"State2 exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<my_machine_::State2&>().entry_counter == 2,"State2 entry not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<my_machine_::State3&>().exit_counter == 2,"State3 exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<my_machine_::State3&>().entry_counter == 2,"State3 entry not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<my_machine_::State4&>().entry_counter == 2,"State4 entry not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<my_machine_::State4&>().exit_counter == 1,"State4 exit not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<my_machine_::State1&>().exit_counter == 2,"State1 exit not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<my_machine_::State1&>().entry_counter == 2,"State1 entry not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<my_machine_::State2&>().exit_counter == 2,"State2 exit not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<my_machine_::State2&>().entry_counter == 2,"State2 entry not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<my_machine_::State3&>().exit_counter == 2,"State3 exit not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<my_machine_::State3&>().entry_counter == 2,"State3 entry not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<my_machine_::State4&>().entry_counter == 2,"State4 entry not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<my_machine_::State4&>().exit_counter == 1,"State4 exit not called correctly");
BOOST_CHECK_MESSAGE(p.always_true_counter == 2,"guard not called correctly");
BOOST_CHECK_MESSAGE(p.always_false_counter == 2,"guard not called correctly");
BOOST_CHECK_MESSAGE(p.state2_to_state3_counter == 2,"action not called correctly");
@@ -14,7 +14,7 @@
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wunused-variable"
#endif
#include <boost/msm/back/state_machine.hpp>
#include "BackCommon.hpp"
#include <boost/msm/front/euml/common.hpp>
#include <boost/msm/front/functor_row.hpp>
#include <boost/msm/front/state_machine_def.hpp>
@@ -23,7 +23,7 @@
#endif
#ifndef BOOST_MSM_NONSTANDALONE_TEST
#define BOOST_TEST_MODULE back11_anonymous_and_guard_test
#define BOOST_TEST_MODULE anonymous_and_guard_test
#endif
#include <boost/test/unit_test.hpp>
@@ -86,9 +86,9 @@ struct Bug : public bmf::state_machine_def<Bug> {
};
// backend
typedef boost::msm::back::state_machine<Bug> MyStateMachine;
typedef get_test_machines<Bug> MyStateMachines;
BOOST_AUTO_TEST_CASE(back11_anonymous_and_guard_test1)
BOOST_AUTO_TEST_CASE_TEMPLATE(anonymous_and_guard_test1, MyStateMachine, MyStateMachines)
{
MyStateMachine sm;
sm.start();
@@ -97,7 +97,7 @@ BOOST_AUTO_TEST_CASE(back11_anonymous_and_guard_test1)
BOOST_CHECK_MESSAGE(sm.current_state()[1] == 3, "Completed should be active");
}
BOOST_AUTO_TEST_CASE(back11_anonymous_and_guard_test2)
BOOST_AUTO_TEST_CASE_TEMPLATE(anonymous_and_guard_test2, MyStateMachine, MyStateMachines)
{
MyStateMachine sm;
sm.start();
+18 -18
View File
@@ -9,11 +9,11 @@
// http://www.boost.org/LICENSE_1_0.txt)
// back-end
#include <boost/msm/back/state_machine.hpp>
#include "BackCommon.hpp"
#include <boost/msm/front/euml/euml.hpp>
#ifndef BOOST_MSM_NONSTANDALONE_TEST
#define BOOST_TEST_MODULE MyTest
#define BOOST_TEST_MODULE anonymous_euml_test
#endif
#include <boost/test/unit_test.hpp>
@@ -107,11 +107,11 @@ namespace
my_machine_) //fsm name
// Pick a back-end
typedef msm::back::state_machine<my_machine_> my_machine;
typedef get_test_machines<my_machine_> my_machines;
//static char const* const state_names[] = { "State1", "State2", "State3", "State4" };
BOOST_AUTO_TEST_CASE( my_test )
BOOST_AUTO_TEST_CASE_TEMPLATE( anonymous_euml_test, my_machine, my_machines )
{
my_machine p;
@@ -119,19 +119,19 @@ namespace
// in this case it will also immediately trigger all anonymous transitions
p.start();
BOOST_CHECK_MESSAGE(p.current_state()[0] == 3,"State4 should be active"); //State4
BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(State1)&>().get_attribute(exit_counter) == 1,
BOOST_CHECK_MESSAGE(p.template get_state<BOOST_MSM_EUML_STATE_NAME(State1)&>().get_attribute(exit_counter) == 1,
"State1 exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(State1)&>().get_attribute(entry_counter) == 1,
BOOST_CHECK_MESSAGE(p.template get_state<BOOST_MSM_EUML_STATE_NAME(State1)&>().get_attribute(entry_counter) == 1,
"State1 entry not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(State2)&>().get_attribute(exit_counter) == 1,
BOOST_CHECK_MESSAGE(p.template get_state<BOOST_MSM_EUML_STATE_NAME(State2)&>().get_attribute(exit_counter) == 1,
"State2 exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(State2)&>().get_attribute(entry_counter) == 1,
BOOST_CHECK_MESSAGE(p.template get_state<BOOST_MSM_EUML_STATE_NAME(State2)&>().get_attribute(entry_counter) == 1,
"State2 entry not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(State3)&>().get_attribute(exit_counter) == 1,
BOOST_CHECK_MESSAGE(p.template get_state<BOOST_MSM_EUML_STATE_NAME(State3)&>().get_attribute(exit_counter) == 1,
"State3 exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(State3)&>().get_attribute(entry_counter) == 1,
BOOST_CHECK_MESSAGE(p.template get_state<BOOST_MSM_EUML_STATE_NAME(State3)&>().get_attribute(entry_counter) == 1,
"State3 entry not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(State4)&>().get_attribute(entry_counter)== 1,
BOOST_CHECK_MESSAGE(p.template get_state<BOOST_MSM_EUML_STATE_NAME(State4)&>().get_attribute(entry_counter)== 1,
"State4 entry not called correctly");
BOOST_CHECK_MESSAGE(p.get_attribute(always_true_counter) == 1,"guard not called correctly");
BOOST_CHECK_MESSAGE(p.get_attribute(always_false_counter) == 1,"guard not called correctly");
@@ -142,19 +142,19 @@ namespace
// this event will bring us back to the initial state and thus, a new "loop" will be started
p.process_event(event1);
BOOST_CHECK_MESSAGE(p.current_state()[0] == 3,"State4 should be active"); //State4
BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(State1)&>().get_attribute(exit_counter) == 2,
BOOST_CHECK_MESSAGE(p.template get_state<BOOST_MSM_EUML_STATE_NAME(State1)&>().get_attribute(exit_counter) == 2,
"State1 exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(State1)&>().get_attribute(entry_counter) == 2,
BOOST_CHECK_MESSAGE(p.template get_state<BOOST_MSM_EUML_STATE_NAME(State1)&>().get_attribute(entry_counter) == 2,
"State1 entry not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(State2)&>().get_attribute(exit_counter) == 2,
BOOST_CHECK_MESSAGE(p.template get_state<BOOST_MSM_EUML_STATE_NAME(State2)&>().get_attribute(exit_counter) == 2,
"State2 exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(State2)&>().get_attribute(entry_counter) == 2,
BOOST_CHECK_MESSAGE(p.template get_state<BOOST_MSM_EUML_STATE_NAME(State2)&>().get_attribute(entry_counter) == 2,
"State2 entry not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(State3)&>().get_attribute(exit_counter) == 2,
BOOST_CHECK_MESSAGE(p.template get_state<BOOST_MSM_EUML_STATE_NAME(State3)&>().get_attribute(exit_counter) == 2,
"State3 exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(State3)&>().get_attribute(entry_counter) == 2,
BOOST_CHECK_MESSAGE(p.template get_state<BOOST_MSM_EUML_STATE_NAME(State3)&>().get_attribute(entry_counter) == 2,
"State3 entry not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(State4)&>().get_attribute(entry_counter)== 2,
BOOST_CHECK_MESSAGE(p.template get_state<BOOST_MSM_EUML_STATE_NAME(State4)&>().get_attribute(entry_counter)== 2,
"State4 entry not called correctly");
BOOST_CHECK_MESSAGE(p.get_attribute(always_true_counter) == 2,"guard not called correctly");
BOOST_CHECK_MESSAGE(p.get_attribute(always_false_counter) == 2,"guard not called correctly");
-182
View File
@@ -1,182 +0,0 @@
// 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)
// back-end
#include <boost/msm/back11/state_machine.hpp>
//front-end
#include <boost/msm/front/state_machine_def.hpp>
#ifndef BOOST_MSM_NONSTANDALONE_TEST
#define BOOST_TEST_MODULE back11_anonymous_test
#endif
#include <boost/test/unit_test.hpp>
namespace msm = boost::msm;
namespace mpl = boost::mpl;
using namespace boost::msm::front;
namespace
{
// events
struct event1 {};
// front-end: define the FSM structure
struct my_machine_ : public msm::front::state_machine_def<my_machine_>
{
unsigned int state2_to_state3_counter;
unsigned int state3_to_state4_counter;
unsigned int always_true_counter;
unsigned int always_false_counter;
my_machine_():
state2_to_state3_counter(0),
state3_to_state4_counter(0),
always_true_counter(0),
always_false_counter(0)
{}
// The list of FSM states
struct State1 : public msm::front::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;
int exit_counter;
};
struct State2 : public msm::front::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;
int exit_counter;
};
struct State3 : public msm::front::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;
int exit_counter;
};
struct State4 : public msm::front::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;
int exit_counter;
};
// the initial state of the player SM. Must be defined
typedef State1 initial_state;
// transition actions
void State2ToState3(none const&) { ++state2_to_state3_counter; }
void State3ToState4(none const&) { ++state3_to_state4_counter; }
// guard conditions
bool always_true(none const& )
{
++always_true_counter;
return true;
}
bool always_false(none const& )
{
++always_false_counter;
return false;
}
typedef my_machine_ p; // makes transition table cleaner
// Transition table for player
struct transition_table : boost::fusion::vector<
// Start Event Next Action Guard
// +---------+-------------+---------+---------------------+----------------------+
_row < State1 , none , State2 >,
a_row < State2 , none , State3 , &p::State2ToState3 >,
// +---------+-------------+---------+---------------------+----------------------+
row < State3 , none , State4 , &p::State3ToState4 , &p::always_true >,
g_row < State3 , none , State4 , &p::always_false >,
_row < State4 , event1 , State1 >
// +---------+-------------+---------+---------------------+----------------------+
> {};
// Replaces the default no-transition response.
template <class FSM,class Event>
void no_transition(Event const&, FSM&,int)
{
BOOST_FAIL("no_transition called!");
}
// init counters
template <class Event,class FSM>
void on_entry(Event const&,FSM& fsm)
{
fsm.template get_state<my_machine_::State1&>().entry_counter=0;
fsm.template get_state<my_machine_::State1&>().exit_counter=0;
fsm.template get_state<my_machine_::State2&>().entry_counter=0;
fsm.template get_state<my_machine_::State2&>().exit_counter=0;
fsm.template get_state<my_machine_::State3&>().entry_counter=0;
fsm.template get_state<my_machine_::State3&>().exit_counter=0;
fsm.template get_state<my_machine_::State4&>().entry_counter=0;
fsm.template get_state<my_machine_::State4&>().exit_counter=0;
}
};
// Pick a back-end
typedef msm::back11::state_machine<my_machine_> my_machine;
//static char const* const state_names[] = { "State1", "State2", "State3", "State4" };
BOOST_AUTO_TEST_CASE( back11_anonymous_test )
{
my_machine p;
// needed to start the highest-level SM. This will call on_entry and mark the start of the SM
// in this case it will also immediately trigger all anonymous transitions
p.start();
BOOST_CHECK_MESSAGE(p.current_state()[0] == 3,"State4 should be active"); //State4
BOOST_CHECK_MESSAGE(p.get_state<my_machine_::State1&>().exit_counter == 1,"State1 exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<my_machine_::State1&>().entry_counter == 1,"State1 entry not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<my_machine_::State2&>().exit_counter == 1,"State2 exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<my_machine_::State2&>().entry_counter == 1,"State2 entry not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<my_machine_::State3&>().exit_counter == 1,"State3 exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<my_machine_::State3&>().entry_counter == 1,"State3 entry not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<my_machine_::State4&>().entry_counter == 1,"State4 entry not called correctly");
BOOST_CHECK_MESSAGE(p.always_true_counter == 1,"guard not called correctly");
BOOST_CHECK_MESSAGE(p.always_false_counter == 1,"guard not called correctly");
BOOST_CHECK_MESSAGE(p.state2_to_state3_counter == 1,"action not called correctly");
BOOST_CHECK_MESSAGE(p.state3_to_state4_counter == 1,"action not called correctly");
// this event will bring us back to the initial state and thus, a new "loop" will be started
p.process_event(event1());
BOOST_CHECK_MESSAGE(p.current_state()[0] == 3,"State4 should be active"); //State4
BOOST_CHECK_MESSAGE(p.get_state<my_machine_::State1&>().exit_counter == 2,"State1 exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<my_machine_::State1&>().entry_counter == 2,"State1 entry not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<my_machine_::State2&>().exit_counter == 2,"State2 exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<my_machine_::State2&>().entry_counter == 2,"State2 entry not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<my_machine_::State3&>().exit_counter == 2,"State3 exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<my_machine_::State3&>().entry_counter == 2,"State3 entry not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<my_machine_::State4&>().entry_counter == 2,"State4 entry not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<my_machine_::State4&>().exit_counter == 1,"State4 exit not called correctly");
BOOST_CHECK_MESSAGE(p.always_true_counter == 2,"guard not called correctly");
BOOST_CHECK_MESSAGE(p.always_false_counter == 2,"guard not called correctly");
BOOST_CHECK_MESSAGE(p.state2_to_state3_counter == 2,"action not called correctly");
BOOST_CHECK_MESSAGE(p.state3_to_state4_counter == 2,"action not called correctly");
}
}
-262
View File
@@ -1,262 +0,0 @@
// 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)
// back-end
#include <boost/msm/back11/state_machine.hpp>
//front-end
#include <boost/msm/front/state_machine_def.hpp>
#ifndef BOOST_MSM_NONSTANDALONE_TEST
#define BOOST_TEST_MODULE back11_big_with_functors_test
#endif
#include <boost/test/unit_test.hpp>
namespace msm = boost::msm;
namespace mpl = boost::mpl;
using namespace boost::msm::front;
namespace
{
// events
struct event1 {};
struct event2 {};
// front-end: define the FSM structure
struct my_machine_ : public msm::front::state_machine_def<my_machine_>
{
my_machine_()
{}
// The list of FSM states
struct State1 : public msm::front::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 State2 : public msm::front::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 State3 : public msm::front::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 State4 : public msm::front::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 State5 : public msm::front::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 State6 : public msm::front::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 State7 : public msm::front::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 State8 : public msm::front::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 State9 : public msm::front::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 State10 : public msm::front::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 State11 : public msm::front::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 State12 : public msm::front::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;
};
// the initial state of the player SM. Must be defined
typedef State1 initial_state;
// transition actions
// guard conditions
typedef my_machine_ p; // makes transition table cleaner
// Transition table for player
struct transition_table : boost::fusion::vector<
// Start Event Next Action Guard
// +---------+-------------+---------+---------------------+----------------------+
_row < State1 , event1 , State2 >,
_row < State2 , event1 , State3 >,
_row < State3 , event1 , State4 >,
_row < State4 , event1 , State5 >,
_row < State5 , event1 , State6 >,
_row < State6 , event1 , State7 >,
_row < State7 , event1 , State8 >,
_row < State8 , event1 , State9 >,
_row < State9 , event1 , State10 >,
_row < State10 , event1 , State11 >,
_row < State11 , event1 , State12 >,
_row < State12 , event2 , State11 >,
_row < State11 , event2 , State10 >,
_row < State10 , event2 , State9 >,
_row < State9 , event2 , State8 >,
_row < State8 , event2 , State7 >,
_row < State7 , event2 , State6 >,
_row < State6 , event2 , State5 >,
_row < State5 , event2 , State4 >,
_row < State4 , event2 , State3 >,
_row < State3 , event2 , State2 >,
_row < State2 , event2 , State1 >
// +---------+-------------+---------+---------------------+----------------------+
> {};
// Replaces the default no-transition response.
template <class FSM,class Event>
void no_transition(Event const&, FSM&,int)
{
BOOST_FAIL("no_transition called!");
}
// init counters
template <class Event,class FSM>
void on_entry(Event const&,FSM&)
{
}
};
// Pick a back-end
typedef msm::back11::state_machine<my_machine_> my_machine;
BOOST_AUTO_TEST_CASE( back11_big_with_functors_test )
{
my_machine p;
// needed to start the highest-level SM.
p.start();
BOOST_CHECK_MESSAGE(p.current_state()[0] == 0,"State1 should be active"); //State1
BOOST_CHECK_MESSAGE(p.get_state<my_machine_::State1&>().exit_counter == 0,"State1 exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<my_machine_::State1&>().entry_counter == 1,"State1 entry not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<my_machine_::State5&>().exit_counter == 0,"State5 exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<my_machine_::State5&>().entry_counter == 0,"State5 entry not called correctly");
p.process_event(event1());
p.process_event(event1());
p.process_event(event1());
p.process_event(event1());
p.process_event(event1());
p.process_event(event1());
p.process_event(event1());
p.process_event(event1());
p.process_event(event1());
p.process_event(event1());
p.process_event(event1());
BOOST_CHECK_MESSAGE(p.current_state()[0] == 11,"State12 should be active"); //State12
BOOST_CHECK_MESSAGE(p.get_state<my_machine_::State12&>().exit_counter == 0,"State12 exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<my_machine_::State12&>().entry_counter == 1,"State12 entry not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<my_machine_::State2&>().exit_counter == 1,"State2 exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<my_machine_::State2&>().entry_counter == 1,"State2 entry not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<my_machine_::State7&>().exit_counter == 1,"State7 exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<my_machine_::State7&>().entry_counter == 1,"State7 entry not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<my_machine_::State10&>().exit_counter == 1,"State10 exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<my_machine_::State10&>().entry_counter == 1,"State10 entry not called correctly");
p.process_event(event2());
p.process_event(event2());
p.process_event(event2());
p.process_event(event2());
p.process_event(event2());
p.process_event(event2());
p.process_event(event2());
p.process_event(event2());
p.process_event(event2());
p.process_event(event2());
p.process_event(event2());
BOOST_CHECK_MESSAGE(p.current_state()[0] == 0,"State1 should be active"); //State1
BOOST_CHECK_MESSAGE(p.get_state<my_machine_::State1&>().exit_counter == 1,"State1 exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<my_machine_::State1&>().entry_counter == 2,"State1 entry not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<my_machine_::State2&>().exit_counter == 2,"State2 exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<my_machine_::State2&>().entry_counter == 2,"State2 entry not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<my_machine_::State7&>().exit_counter == 2,"State7 exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<my_machine_::State7&>().entry_counter == 2,"State7 entry not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<my_machine_::State10&>().exit_counter == 2,"State10 exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<my_machine_::State10&>().entry_counter == 2,"State10 entry not called correctly");
}
}
-297
View File
@@ -1,297 +0,0 @@
// 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)
// back-end
#include <boost/msm/back11/state_machine.hpp>
//front-end
#include <boost/msm/front/state_machine_def.hpp>
#ifndef BOOST_MSM_NONSTANDALONE_TEST
#define BOOST_TEST_MODULE back11_entries_test
#endif
#include <boost/test/unit_test.hpp>
namespace msm = boost::msm;
namespace mpl = boost::mpl;
namespace fusion = boost::fusion;
namespace
{
// events
struct event1 {};
struct event2 {};
struct event3 {};
struct event4 {};
struct event5 {};
struct event6
{
event6(){}
template <class Event>
event6(Event const&){}
};
// front-end: define the FSM structure
struct Fsm_ : public msm::front::state_machine_def<Fsm_>
{
// The list of FSM states
struct State1 : public msm::front::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;
int exit_counter;
};
struct State2 : public msm::front::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;
int exit_counter;
};
struct SubFsm2_ : public msm::front::state_machine_def<SubFsm2_>
{
typedef msm::back11::state_machine<SubFsm2_> SubFsm2;
unsigned int entry_action_counter;
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;
int exit_counter;
struct SubState1 : public msm::front::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;
int exit_counter;
};
struct SubState1b : public msm::front::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;
int exit_counter;
};
struct SubState2 : public msm::front::state<> , public msm::front::explicit_entry<0>
{
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;
int exit_counter;
};
struct SubState2b : public msm::front::state<> , public msm::front::explicit_entry<1>
{
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;
int exit_counter;
};
// test with a pseudo entry
struct PseudoEntry1 : public msm::front::entry_pseudo_state<0>
{
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;
int exit_counter;
};
struct SubState3 : public msm::front::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;
int exit_counter;
};
struct PseudoExit1 : public msm::front::exit_pseudo_state<event6>
{
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;
int exit_counter;
};
// action methods
void entry_action(event4 const&)
{
++entry_action_counter;
}
// the initial state. Must be defined
typedef fusion::vector<SubState1,SubState1b> initial_state;
typedef fusion::vector<SubState2b> explicit_creation;
// Transition table for SubFsm2
struct transition_table : fusion::vector<
// Start Event Next Action Guard
// +--------------+-------------+------------+------------------------+----------------------+
a_row < PseudoEntry1 , event4 , SubState3 ,&SubFsm2_::entry_action >,
_row < SubState2 , event6 , SubState1 >,
_row < SubState3 , event5 , PseudoExit1 >
// +--------------+-------------+------------+------------------------+----------------------+
> {};
// Replaces the default no-transition response.
template <class FSM,class Event>
void no_transition(Event const& , FSM&,int)
{
BOOST_FAIL("no_transition called!");
}
};
typedef msm::back11::state_machine<SubFsm2_> SubFsm2;
// the initial state of the player SM. Must be defined
typedef State1 initial_state;
// transition actions
// guard conditions
// Transition table for Fsm
struct transition_table : fusion::vector<
// Start Event Next Action Guard
// +---------------------+--------+------------------------------------+-------+--------+
_row < State1 , event1 , SubFsm2 >,
_row < State1 , event2 , SubFsm2::direct<SubFsm2_::SubState2> >,
_row < State1 , event3 , fusion::vector<SubFsm2::direct<SubFsm2_::SubState2>,
SubFsm2::direct<SubFsm2_::SubState2b> > >,
_row < State1 , event4 , SubFsm2::entry_pt
<SubFsm2_::PseudoEntry1> >,
// +---------------------+--------+------------------------------------+-------+--------+
_row < SubFsm2 , event1 , State1 >,
_row < SubFsm2::exit_pt
<SubFsm2_::PseudoExit1>, event6 , State2 >
// +---------------------+--------+------------------------------------+-------+--------+
> {};
// Replaces the default no-transition response.
template <class FSM,class Event>
void no_transition(Event const& , FSM&,int )
{
BOOST_FAIL("no_transition called!");
}
// init counters
template <class Event,class FSM>
void on_entry(Event const&,FSM& fsm)
{
fsm.template get_state<Fsm_::State1&>().entry_counter=0;
fsm.template get_state<Fsm_::State1&>().exit_counter=0;
fsm.template get_state<Fsm_::State2&>().entry_counter=0;
fsm.template get_state<Fsm_::State2&>().exit_counter=0;
fsm.template get_state<Fsm_::SubFsm2&>().entry_counter=0;
fsm.template get_state<Fsm_::SubFsm2&>().exit_counter=0;
fsm.template get_state<Fsm_::SubFsm2&>().entry_action_counter=0;
fsm.template get_state<Fsm_::SubFsm2&>().template get_state<Fsm_::SubFsm2::SubState1&>().entry_counter=0;
fsm.template get_state<Fsm_::SubFsm2&>().template get_state<Fsm_::SubFsm2::SubState1&>().exit_counter=0;
fsm.template get_state<Fsm_::SubFsm2&>().template get_state<Fsm_::SubFsm2::SubState1b&>().entry_counter=0;
fsm.template get_state<Fsm_::SubFsm2&>().template get_state<Fsm_::SubFsm2::SubState1b&>().exit_counter=0;
fsm.template get_state<Fsm_::SubFsm2&>().template get_state<Fsm_::SubFsm2::SubState2&>().entry_counter=0;
fsm.template get_state<Fsm_::SubFsm2&>().template get_state<Fsm_::SubFsm2::SubState2&>().exit_counter=0;
fsm.template get_state<Fsm_::SubFsm2&>().template get_state<Fsm_::SubFsm2::SubState2b&>().entry_counter=0;
fsm.template get_state<Fsm_::SubFsm2&>().template get_state<Fsm_::SubFsm2::SubState2b&>().exit_counter=0;
fsm.template get_state<Fsm_::SubFsm2&>().template get_state<Fsm_::SubFsm2::SubState3&>().entry_counter=0;
fsm.template get_state<Fsm_::SubFsm2&>().template get_state<Fsm_::SubFsm2::SubState3&>().exit_counter=0;
fsm.template get_state<Fsm_::SubFsm2&>().template get_state<Fsm_::SubFsm2::PseudoEntry1&>().entry_counter=0;
fsm.template get_state<Fsm_::SubFsm2&>().template get_state<Fsm_::SubFsm2::PseudoEntry1&>().exit_counter=0;
fsm.template get_state<Fsm_::SubFsm2&>().template get_state<Fsm_::SubFsm2::exit_pt<SubFsm2_::PseudoExit1>&>().entry_counter=0;
fsm.template get_state<Fsm_::SubFsm2&>().template get_state<Fsm_::SubFsm2::exit_pt<SubFsm2_::PseudoExit1>&>().exit_counter=0;
}
};
typedef msm::back11::state_machine<Fsm_> Fsm;
// static char const* const state_names[] = { "State1", "SubFsm2","State2" };
BOOST_AUTO_TEST_CASE( back11_entries_test )
{
Fsm p;
p.start();
BOOST_CHECK_MESSAGE(p.get_state<Fsm_::State1&>().entry_counter == 1,"State1 entry not called correctly");
p.process_event(event1());
p.process_event(event1());
BOOST_CHECK_MESSAGE(p.current_state()[0] == 0,"State1 should be active");
BOOST_CHECK_MESSAGE(p.get_state<Fsm_::State1&>().exit_counter == 1,"State1 exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<Fsm_::State1&>().entry_counter == 2,"State1 entry not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<Fsm_::SubFsm2&>().exit_counter == 1,"SubFsm2 exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<Fsm_::SubFsm2&>().entry_counter == 1,"SubFsm2 entry not called correctly");
p.process_event(event2());
p.process_event(event6());
p.process_event(event1());
BOOST_CHECK_MESSAGE(p.current_state()[0] == 0,"State1 should be active");
BOOST_CHECK_MESSAGE(p.get_state<Fsm_::State1&>().exit_counter == 2,"State1 exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<Fsm_::State1&>().entry_counter == 3,"State1 entry not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<Fsm_::SubFsm2&>().exit_counter == 2,"SubFsm2 exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<Fsm_::SubFsm2&>().entry_counter == 2,"SubFsm2 entry not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<Fsm_::SubFsm2&>().get_state<Fsm_::SubFsm2_::SubState2&>().entry_counter == 1,
"SubFsm2::SubState2 entry not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<Fsm_::SubFsm2&>().get_state<Fsm_::SubFsm2_::SubState2&>().exit_counter == 1,
"SubFsm2::SubState2 exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<Fsm_::SubFsm2&>().get_state<Fsm_::SubFsm2_::SubState1&>().entry_counter == 2,
"SubFsm2::SubState1 entry not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<Fsm_::SubFsm2&>().get_state<Fsm_::SubFsm2_::SubState1&>().exit_counter == 2,
"SubFsm2::SubState1 exit not called correctly");
p.process_event(event3());
p.process_event(event1());
BOOST_CHECK_MESSAGE(p.current_state()[0] == 0,"State1 should be active");
BOOST_CHECK_MESSAGE(p.get_state<Fsm_::State1&>().exit_counter == 3,"State1 exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<Fsm_::State1&>().entry_counter == 4,"State1 entry not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<Fsm_::SubFsm2&>().exit_counter == 3,"SubFsm2 exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<Fsm_::SubFsm2&>().entry_counter == 3,"SubFsm2 entry not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<Fsm_::SubFsm2&>().get_state<Fsm_::SubFsm2_::SubState2&>().entry_counter == 2,
"SubFsm2::SubState2 entry not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<Fsm_::SubFsm2&>().get_state<Fsm_::SubFsm2_::SubState2&>().exit_counter == 2,
"SubFsm2::SubState2 exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<Fsm_::SubFsm2&>().get_state<Fsm_::SubFsm2_::SubState2b&>().entry_counter == 1,
"SubFsm2::SubState2b entry not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<Fsm_::SubFsm2&>().get_state<Fsm_::SubFsm2_::SubState2b&>().exit_counter == 1,
"SubFsm2::SubState2b exit not called correctly");
p.process_event(event4());
p.process_event(event5());
BOOST_CHECK_MESSAGE(p.current_state()[0] == 2,"State2 should be active");
BOOST_CHECK_MESSAGE(p.get_state<Fsm_::State1&>().exit_counter == 4,"State1 exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<Fsm_::State2&>().entry_counter == 1,"State2 entry not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<Fsm_::SubFsm2&>().exit_counter == 4,"SubFsm2 exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<Fsm_::SubFsm2&>().entry_counter == 4,"SubFsm2 entry not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<Fsm_::SubFsm2&>().get_state<Fsm_::SubFsm2_::PseudoEntry1&>().entry_counter == 1,
"SubFsm2::PseudoEntry1 entry not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<Fsm_::SubFsm2&>().get_state<Fsm_::SubFsm2_::PseudoEntry1&>().exit_counter == 1,
"SubFsm2::PseudoEntry1 exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<Fsm_::SubFsm2&>().get_state<Fsm_::SubFsm2_::SubState3&>().entry_counter == 1,
"SubFsm2::SubState3 entry not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<Fsm_::SubFsm2&>().get_state<Fsm_::SubFsm2_::SubState3&>().exit_counter == 1,
"SubFsm2::SubState3 exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<Fsm_::SubFsm2&>().get_state<Fsm_::SubFsm2::exit_pt<Fsm_::SubFsm2_::PseudoExit1>&>().entry_counter == 1,
"SubFsm2::PseudoExit1 entry not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<Fsm_::SubFsm2&>().get_state<Fsm_::SubFsm2::exit_pt<Fsm_::SubFsm2_::PseudoExit1>&>().exit_counter == 1,
"SubFsm2::PseudoExit1 exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<Fsm_::SubFsm2&>().entry_action_counter == 1,"Action not called correctly");
}
}
-358
View File
@@ -1,358 +0,0 @@
// 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)
// back-end
#include <boost/msm/back11/state_machine.hpp>
//front-end
#include <boost/msm/front/state_machine_def.hpp>
#ifndef BOOST_MSM_NONSTANDALONE_TEST
#define BOOST_TEST_MODULE Back11HistoryTest
#endif
#include <boost/test/unit_test.hpp>
namespace msm = boost::msm;
namespace mpl = boost::mpl;
namespace
{
// events
struct play {};
struct end_pause {};
struct stop {};
struct pause {};
struct open_close {};
struct NextSong {};
struct PreviousSong {};
struct cd_detected
{
cd_detected(std::string name)
: name(name)
{}
std::string name;
};
// front-end: define the FSM structure
struct player_ : public msm::front::state_machine_def<player_>
{
unsigned int start_playback_counter;
unsigned int can_close_drawer_counter;
player_():
start_playback_counter(0),
can_close_drawer_counter(0)
{}
// The list of FSM states
struct Empty : public msm::front::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;
int exit_counter;
};
struct Open : public msm::front::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;
int exit_counter;
};
// sm_ptr still supported but deprecated as functors are a much better way to do the same thing
struct Stopped : public msm::front::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;
int exit_counter;
};
struct Playing_ : public msm::front::state_machine_def<Playing_>
{
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;
int exit_counter;
unsigned int start_next_song_counter;
unsigned int start_prev_song_guard_counter;
Playing_():
start_next_song_counter(0),
start_prev_song_guard_counter(0)
{}
// The list of FSM states
struct Song1 : public msm::front::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;
int exit_counter;
};
struct Song2 : public msm::front::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;
int exit_counter;
};
struct Song3 : public msm::front::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;
int exit_counter;
};
// the initial state. Must be defined
typedef Song1 initial_state;
// transition actions
void start_next_song(NextSong const&) {++start_next_song_counter; }
void start_prev_song(PreviousSong const&) { }
// guard conditions
bool start_prev_song_guard(PreviousSong const&) {++start_prev_song_guard_counter;return true; }
typedef Playing_ pl; // makes transition table cleaner
// Transition table for Playing
struct transition_table : mpl::vector4<
// Start Event Next Action Guard
// +---------+-------------+---------+---------------------+----------------------+
_row < Song1 , NextSong , Song2 >,
row < Song2 , PreviousSong, Song1 , &pl::start_prev_song,&pl::start_prev_song_guard>,
a_row < Song2 , NextSong , Song3 , &pl::start_next_song >,
g_row < Song3 , PreviousSong, Song2 ,&pl::start_prev_song_guard>
// +---------+-------------+---------+---------------------+----------------------+
> {};
// Replaces the default no-transition response.
template <class FSM,class Event>
void no_transition(Event const&, FSM&,int)
{
BOOST_FAIL("no_transition called!");
}
};
// back-end
typedef msm::back11::state_machine<
Playing_,
msm::back11::state_machine<player_>,
msm::back::ShallowHistory<mpl::vector<end_pause> > > Playing;
// state not defining any entry or exit
struct Paused : public msm::front::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;
int exit_counter;
};
// the initial state of the player SM. Must be defined
typedef Empty initial_state;
// transition actions
void start_playback(play const&) {++start_playback_counter; }
void open_drawer(open_close const&) { }
void store_cd_info(cd_detected const&) { }
void stop_playback(stop const&) { }
void pause_playback(pause const&) { }
void resume_playback(end_pause const&) { }
void stop_and_open(open_close const&) { }
void stopped_again(stop const&){}
//guards
bool can_close_drawer(open_close const&)
{
++can_close_drawer_counter;
return true;
}
typedef player_ p; // makes transition table cleaner
// Transition table for player
struct transition_table : mpl::vector<
// Start Event Next Action Guard
// +---------+-------------+---------+---------------------+----------------------+
a_row < Stopped , play , Playing , &p::start_playback >,
a_row < Stopped , open_close , Open , &p::open_drawer >,
_row < Stopped , stop , Stopped >,
// +---------+-------------+---------+---------------------+----------------------+
g_row < Open , open_close , Empty , &p::can_close_drawer >,
// +---------+-------------+---------+---------------------+----------------------+
a_row < Empty , open_close , Open , &p::open_drawer >,
a_row < Empty , cd_detected , Stopped , &p::store_cd_info >,
// +---------+-------------+---------+---------------------+----------------------+
a_row < Playing , stop , Stopped , &p::stop_playback >,
a_row < Playing , pause , Paused , &p::pause_playback >,
a_row < Playing , open_close , Open , &p::stop_and_open >,
// +---------+-------------+---------+---------------------+----------------------+
a_row < Paused , end_pause , Playing , &p::resume_playback >,
a_row < Paused , stop , Stopped , &p::stop_playback >,
a_row < Paused , open_close , Open , &p::stop_and_open >
// +---------+-------------+---------+---------------------+----------------------+
> {};
// Replaces the default no-transition response.
template <class FSM,class Event>
void no_transition(Event const& , FSM&,int )
{
BOOST_FAIL("no_transition called!");
}
// init counters
template <class Event,class FSM>
void on_entry(Event const&,FSM& fsm)
{
fsm.template get_state<player_::Stopped&>().entry_counter=0;
fsm.template get_state<player_::Stopped&>().exit_counter=0;
fsm.template get_state<player_::Open&>().entry_counter=0;
fsm.template get_state<player_::Open&>().exit_counter=0;
fsm.template get_state<player_::Empty&>().entry_counter=0;
fsm.template get_state<player_::Empty&>().exit_counter=0;
fsm.template get_state<player_::Playing&>().entry_counter=0;
fsm.template get_state<player_::Playing&>().exit_counter=0;
fsm.template get_state<player_::Playing&>().template get_state<player_::Playing::Song1&>().entry_counter=0;
fsm.template get_state<player_::Playing&>().template get_state<player_::Playing::Song1&>().exit_counter=0;
fsm.template get_state<player_::Playing&>().template get_state<player_::Playing::Song2&>().entry_counter=0;
fsm.template get_state<player_::Playing&>().template get_state<player_::Playing::Song2&>().exit_counter=0;
fsm.template get_state<player_::Playing&>().template get_state<player_::Playing::Song3&>().entry_counter=0;
fsm.template get_state<player_::Playing&>().template get_state<player_::Playing::Song3&>().exit_counter=0;
fsm.template get_state<player_::Paused&>().entry_counter=0;
fsm.template get_state<player_::Paused&>().exit_counter=0;
}
};
// Pick a back-end
typedef msm::back11::state_machine<player_> player;
// static char const* const state_names[] = { "Stopped", "Open", "Empty", "Playing", "Paused" };
BOOST_AUTO_TEST_CASE(Back11HistoryTest)
{
player p;
p.start();
BOOST_CHECK_MESSAGE(p.get_state<player_::Empty&>().entry_counter == 1,"Empty entry not called correctly");
p.process_event(open_close());
BOOST_CHECK_MESSAGE(p.current_state()[0] == 1,"Open should be active"); //Open
BOOST_CHECK_MESSAGE(p.get_state<player_::Empty&>().exit_counter == 1,"Empty exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::Open&>().entry_counter == 1,"Open entry not called correctly");
p.process_event(open_close());
BOOST_CHECK_MESSAGE(p.current_state()[0] == 2,"Empty should be active"); //Empty
BOOST_CHECK_MESSAGE(p.get_state<player_::Open&>().exit_counter == 1,"Open exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::Empty&>().entry_counter == 2,"Empty entry not called correctly");
BOOST_CHECK_MESSAGE(p.can_close_drawer_counter == 1,"guard not called correctly");
p.process_event(cd_detected("louie, louie"));
BOOST_CHECK_MESSAGE(p.current_state()[0] == 0,"Stopped should be active"); //Stopped
BOOST_CHECK_MESSAGE(p.get_state<player_::Empty&>().exit_counter == 2,"Empty exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::Stopped&>().entry_counter == 1,"Stopped entry not called correctly");
p.process_event(play());
BOOST_CHECK_MESSAGE(p.current_state()[0] == 3,"Playing should be active"); //Playing
BOOST_CHECK_MESSAGE(p.get_state<player_::Stopped&>().exit_counter == 1,"Stopped exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::Playing&>().entry_counter == 1,"Playing entry not called correctly");
BOOST_CHECK_MESSAGE(p.start_playback_counter == 1,"action not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::Playing&>().current_state()[0] == 0,"Song1 should be active");
BOOST_CHECK_MESSAGE(
p.get_state<player_::Playing&>().get_state<player_::Playing::Song1&>().entry_counter == 1,
"Song1 entry not called correctly");
p.process_event(NextSong());
BOOST_CHECK_MESSAGE(p.current_state()[0] == 3,"Playing should be active"); //Playing
BOOST_CHECK_MESSAGE(p.get_state<player_::Playing&>().current_state()[0] == 1,"Song2 should be active");
BOOST_CHECK_MESSAGE(
p.get_state<player_::Playing&>().get_state<player_::Playing::Song2&>().entry_counter == 1,
"Song2 entry not called correctly");
BOOST_CHECK_MESSAGE(
p.get_state<player_::Playing&>().get_state<player_::Playing::Song1&>().exit_counter == 1,
"Song1 exit not called correctly");
BOOST_CHECK_MESSAGE(
p.get_state<player_::Playing&>().start_next_song_counter == 0,
"submachine action not called correctly");
p.process_event(NextSong());
BOOST_CHECK_MESSAGE(p.current_state()[0] == 3,"Playing should be active"); //Playing
BOOST_CHECK_MESSAGE(p.get_state<player_::Playing&>().current_state()[0] == 2,"Song3 should be active");
BOOST_CHECK_MESSAGE(
p.get_state<player_::Playing&>().get_state<player_::Playing::Song3&>().entry_counter == 1,
"Song3 entry not called correctly");
BOOST_CHECK_MESSAGE(
p.get_state<player_::Playing&>().get_state<player_::Playing::Song2&>().exit_counter == 1,
"Song2 exit not called correctly");
BOOST_CHECK_MESSAGE(
p.get_state<player_::Playing&>().start_next_song_counter == 1,
"submachine action not called correctly");
p.process_event(PreviousSong());
BOOST_CHECK_MESSAGE(p.current_state()[0] == 3,"Playing should be active"); //Playing
BOOST_CHECK_MESSAGE(p.get_state<player_::Playing&>().current_state()[0] == 1,"Song2 should be active");
BOOST_CHECK_MESSAGE(
p.get_state<player_::Playing&>().get_state<player_::Playing::Song2&>().entry_counter == 2,
"Song2 entry not called correctly");
BOOST_CHECK_MESSAGE(
p.get_state<player_::Playing&>().get_state<player_::Playing::Song3&>().exit_counter == 1,
"Song3 exit not called correctly");
BOOST_CHECK_MESSAGE(
p.get_state<player_::Playing&>().start_prev_song_guard_counter == 1,
"submachine guard not called correctly");
p.process_event(pause());
BOOST_CHECK_MESSAGE(p.current_state()[0] == 4,"Paused should be active"); //Paused
BOOST_CHECK_MESSAGE(p.get_state<player_::Playing&>().exit_counter == 1,"Playing exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::Paused&>().entry_counter == 1,"Paused entry not called correctly");
// go back to Playing
p.process_event(end_pause());
BOOST_CHECK_MESSAGE(p.current_state()[0] == 3,"Playing should be active"); //Playing
BOOST_CHECK_MESSAGE(p.get_state<player_::Paused&>().exit_counter == 1,"Paused exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::Playing&>().entry_counter == 2,"Playing entry not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::Playing&>().current_state()[0] == 1,"Song2 should be active");
BOOST_CHECK_MESSAGE(
p.get_state<player_::Playing&>().get_state<player_::Playing::Song2&>().entry_counter == 3,
"Song2 entry not called correctly");
p.process_event(pause());
BOOST_CHECK_MESSAGE(p.current_state()[0] == 4,"Paused should be active"); //Paused
BOOST_CHECK_MESSAGE(p.get_state<player_::Playing&>().exit_counter == 2,"Playing exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::Paused&>().entry_counter == 2,"Paused entry not called correctly");
p.process_event(stop());
BOOST_CHECK_MESSAGE(p.current_state()[0] == 0,"Stopped should be active"); //Stopped
BOOST_CHECK_MESSAGE(p.get_state<player_::Paused&>().exit_counter == 2,"Paused exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::Stopped&>().entry_counter == 2,"Stopped entry not called correctly");
p.process_event(stop());
BOOST_CHECK_MESSAGE(p.current_state()[0] == 0,"Stopped should be active"); //Stopped
BOOST_CHECK_MESSAGE(p.get_state<player_::Stopped&>().exit_counter == 2,"Stopped exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::Stopped&>().entry_counter == 3,"Stopped entry not called correctly");
p.process_event(play());
BOOST_CHECK_MESSAGE(p.get_state<player_::Playing&>().current_state()[0] == 0,"Song1 should be active");
BOOST_CHECK_MESSAGE(
p.get_state<player_::Playing&>().get_state<player_::Playing::Song1&>().entry_counter == 2,
"Song1 entry not called correctly");
}
}
-126
View File
@@ -1,126 +0,0 @@
// 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 <boost/fusion/adapted/std_tuple.hpp>
#include <boost/fusion/include/std_tuple.hpp>
// back-end
#include <boost/msm/back11/state_machine.hpp>
//front-end
#include <boost/msm/front/state_machine_def.hpp>
// functors
#include <boost/msm/front/functor_row.hpp>
// for And_ operator
#include <boost/msm/front/operator.hpp>
#ifndef BOOST_MSM_NONSTANDALONE_TEST
#define BOOST_TEST_MODULE back11_kleene_deferred_test
#endif
#include <boost/test/unit_test.hpp>
using namespace std;
namespace msm = boost::msm;
namespace mpl = boost::mpl;
using namespace msm::front;
namespace
{
// events
struct event1 {};
struct event2 {};
// front-end: define the FSM structure
struct fsm_ : public msm::front::state_machine_def<fsm_>
{
// we want deferred events and no state requires deferred events (only the fsm in the
// transition table), so the fsm does.
typedef int activate_deferred_events;
// The list of FSM states
struct StateA : public msm::front::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 StateB : public msm::front::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;
};
// the initial state of the player SM. Must be defined
typedef StateA initial_state;
struct is_event1
{
template <class EVT, class FSM, class SourceState, class TargetState>
bool operator()(EVT const& evt, FSM&, SourceState&, TargetState&)
{
bool is_deferred = boost::any_cast<event1>(&evt) != 0;
return is_deferred;
}
};
typedef fsm_ p; // makes transition table cleaner
// Transition table for player
struct transition_table : boost::fusion::vector<
// Start Event Next Action Guard
// +---------+-------------+---------+---------------------+----------------------+
Row < StateA , event1 , StateB , none , none >,
Row < StateB , boost::any , none , Defer , is_event1 >,
Row < StateB , event2 , StateA , none , none >
// +---------+-------------+---------+---------------------+----------------------+
>/*>::type*/ {};
// Replaces the default no-transition response.
template <class FSM,class Event>
void no_transition(Event const&, FSM&,int)
{
BOOST_FAIL("no_transition called!");
}
};
// Pick a back-end
typedef msm::back11::state_machine<fsm_> Fsm;
BOOST_AUTO_TEST_CASE(back11_kleene_deferred_test)
{
Fsm fsm;
fsm.start();
BOOST_CHECK_MESSAGE(fsm.get_state<fsm_::StateA&>().entry_counter == 1,"StateA entry not called correctly");
fsm.process_event(event1());
BOOST_CHECK_MESSAGE(fsm.current_state()[0] == 1,"StateB should be active");
BOOST_CHECK_MESSAGE(fsm.get_state<fsm_::StateA&>().exit_counter == 1,"StateA exit not called correctly");
BOOST_CHECK_MESSAGE(fsm.get_state<fsm_::StateB&>().entry_counter == 1,"StateB entry not called correctly");
fsm.process_event(event1());
BOOST_CHECK_MESSAGE(fsm.current_state()[0] == 1, "StateB should be active");
BOOST_CHECK_MESSAGE(fsm.get_state<fsm_::StateA&>().exit_counter == 1, "StateA exit not called correctly");
BOOST_CHECK_MESSAGE(fsm.get_state<fsm_::StateB&>().entry_counter == 1, "StateB entry not called correctly");
fsm.process_event(event2());
BOOST_CHECK_MESSAGE(fsm.current_state()[0] == 1, "StateB should be active");
BOOST_CHECK_MESSAGE(fsm.get_state<fsm_::StateA&>().exit_counter == 2, "StateA exit not called correctly");
BOOST_CHECK_MESSAGE(fsm.get_state<fsm_::StateB&>().entry_counter == 2, "StateB entry not called correctly");
}
}
-106
View File
@@ -1,106 +0,0 @@
// Copyright 2024 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>
// back-end
#include <boost/msm/back11/state_machine.hpp>
//front-end
#include <boost/msm/front/functor_row.hpp>
#include <boost/msm/front/state_machine_def.hpp>
#ifndef BOOST_MSM_NONSTANDALONE_TEST
#define BOOST_TEST_MODULE back11_many_deferred_transitions
#endif
#include <boost/test/unit_test.hpp>
namespace msm = boost::msm;
namespace msmf = boost::msm::front;
namespace mpl = boost::mpl;
namespace
{
// ----- Events
struct Event1 {};
struct Event2 {};
struct Event3 {};
struct Event4 {};
// ----- State machine
struct Sm1_ :msmf::state_machine_def<Sm1_> {
// States
struct State1 :msmf::state<> {
template <class Event, class Fsm>
void on_entry(Event const&, Fsm&) const {
}
};
struct State2 :msmf::state<> {
template <class Event, class Fsm>
void on_entry(Event const&, Fsm&) const {
}
};
struct State3 :msmf::state<> {
template <class Event, class Fsm>
void on_entry(Event const&, Fsm&) const {
}
};
struct State4 :msmf::state<> {
template <class Event, class Fsm>
void on_entry(Event const&, Fsm&) const {
}
};
struct State5 :msmf::state<> {
template <class Event, class Fsm>
void on_entry(Event const&, Fsm&) const {
}
};
// Set initial state
typedef State1 initial_state;
// Enable deferred capability
typedef int activate_deferred_events;
// Transition table
struct transition_table :mpl::vector<
// Start Event Next Action Guard
msmf::Row < State1, Event1, msmf::none, msmf::Defer>,
msmf::Row < State1, Event2, msmf::none, msmf::Defer>,
msmf::Row < State1, Event3, msmf::none, msmf::Defer>,
msmf::Row < State1, Event4, State2 , msmf::none>,
msmf::Row < State2, Event3, msmf::none, msmf::Defer>,
msmf::Row < State2, Event1, msmf::none, msmf::Defer>,
msmf::Row < State2, Event2, State3 , msmf::none>,
msmf::Row < State3, Event1, State4 , msmf::none>,
msmf::Row < State3, Event3, State5 , msmf::none>,
msmf::Row < State4, Event3, State5 , msmf::none>,
msmf::Row < State5, Event1, State4 , msmf::none>
> {};
template <class Fsm, class Event>
void no_transition(Event const&, Fsm&, int /*state*/) {
}
};
// Pick a back-end
typedef msm::back11::state_machine<Sm1_> Sm1;
BOOST_AUTO_TEST_CASE(back11_many_deferred_transitions)
{
Sm1 sm1;
sm1.start();
sm1.process_event(Event1());
sm1.process_event(Event2());
sm1.process_event(Event3());
sm1.process_event(Event4());
BOOST_CHECK_MESSAGE(sm1.current_state()[0] == 4, "State5 should be active");
}
}
-509
View File
@@ -1,509 +0,0 @@
// 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)
// back-end
#include <boost/msm/back11/state_machine.hpp>
//front-end
#include <boost/msm/front/state_machine_def.hpp>
#include <boost/msm/front/functor_row.hpp>
#ifndef BOOST_MSM_NONSTANDALONE_TEST
#define BOOST_TEST_MODULE back11_orthogonal_deferred3_test
#endif
#include <boost/test/unit_test.hpp>
namespace msm = boost::msm;
namespace mpl = boost::mpl;
using namespace boost::msm::front;
namespace
{
// events
struct play {};
struct end_pause {};
struct stop {};
struct pause {};
struct open_close {};
struct NextSong {};
struct PreviousSong {};
struct error_found {};
struct end_error {};
struct do_terminate {};
// Flags. Allow information about a property of the current state
struct PlayingPaused{};
struct CDLoaded {};
struct FirstSongPlaying {};
// A "complicated" event type that carries some data.
struct cd_detected
{
cd_detected(std::string name)
: name(name)
{}
std::string name;
};
// front-end: define the FSM structure
struct player_ : public msm::front::state_machine_def<player_>
{
// we want deferred events and no state requires deferred events (only the fsm in the
// transition table), so the fsm does.
typedef int activate_deferred_events;
unsigned int start_playback_counter;
unsigned int can_close_drawer_counter;
unsigned int report_error_counter;
unsigned int report_end_error_counter;
player_():
start_playback_counter(0),
can_close_drawer_counter(0),
report_error_counter(0),
report_end_error_counter(0)
{}
// The list of FSM states
struct Empty : public msm::front::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;
int exit_counter;
};
struct Open : public msm::front::state<>
{
typedef boost::fusion::vector<CDLoaded> flag_list;
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;
int exit_counter;
};
struct Stopped : public msm::front::state<>
{
typedef boost::fusion::vector<CDLoaded> flag_list;
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;
int exit_counter;
};
// the player state machine contains a state which is himself a state machine
// as you see, no need to declare it anywhere so Playing can be developed separately
// by another team in another module. For simplicity I just declare it inside player
struct Playing_ : public msm::front::state_machine_def<Playing_>
{
// when playing, the CD is loaded and we are in either pause or playing (duh)
typedef boost::fusion::vector<PlayingPaused,CDLoaded> flag_list;
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;
int exit_counter;
unsigned int start_next_song_counter;
unsigned int start_prev_song_guard_counter;
Playing_():
start_next_song_counter(0),
start_prev_song_guard_counter(0)
{}
// The list of FSM states
struct Song1 : public msm::front::state<>
{
typedef boost::fusion::vector<FirstSongPlaying> flag_list;
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;
int exit_counter;
};
struct Song2 : public msm::front::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;
int exit_counter;
};
struct Song3 : public msm::front::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;
int exit_counter;
};
// the initial state. Must be defined
typedef Song1 initial_state;
// transition actions
void start_next_song(NextSong const&) {++start_next_song_counter; }
void start_prev_song(PreviousSong const&) { }
// guard conditions
bool start_prev_song_guard(PreviousSong const&) {++start_prev_song_guard_counter;return true; }
typedef Playing_ pl; // makes transition table cleaner
// Transition table for Playing
struct transition_table : boost::fusion::vector<
// Start Event Next Action Guard
// +---------+-------------+---------+---------------------+----------------------+
_row < Song1 , NextSong , Song2 >,
row < Song2 , PreviousSong, Song1 , &pl::start_prev_song,&pl::start_prev_song_guard>,
a_row < Song2 , NextSong , Song3 , &pl::start_next_song >,
g_row < Song3 , PreviousSong, Song2 ,&pl::start_prev_song_guard>
// +---------+-------------+---------+---------------------+----------------------+
> {};
// Replaces the default no-transition response.
template <class FSM,class Event>
void no_transition(Event const&, FSM&,int)
{
BOOST_FAIL("no_transition called!");
}
};
// back-end
typedef msm::back11::state_machine<Playing_> Playing;
// state not defining any entry or exit
struct Paused : public msm::front::state<>
{
typedef boost::fusion::vector<PlayingPaused,CDLoaded> flag_list;
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;
int exit_counter;
};
struct AllOk : public msm::front::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;
int exit_counter;
};
// this state is also made terminal so that all the events are blocked
struct ErrorMode : //public msm::front::terminate_state<> // ErrorMode terminates the state machine
public msm::front::interrupt_state<end_error/*boost::fusion::vector<end_error>*/> // ErroMode just interrupts. Will resume if
// the event end_error is generated
{
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;
int exit_counter;
};
struct ErrorTerminate : public msm::front::terminate_state<> // terminates the state machine
{
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;
int exit_counter;
};
// the initial state of the player SM. Must be defined
typedef boost::fusion::vector<Empty,AllOk> initial_state;
// transition actions
void start_playback(play const&) {++start_playback_counter; }
void open_drawer(open_close const&) { }
void store_cd_info(cd_detected const&) { }
void stop_playback(stop const&) { }
void pause_playback(pause const&) { }
void resume_playback(end_pause const&) { }
void stop_and_open(open_close const&) { }
void stopped_again(stop const&){}
void report_error(error_found const&) {++report_error_counter;}
void report_end_error(end_error const&) {++report_end_error_counter;}
//guards
bool can_close_drawer(open_close const&)
{
++can_close_drawer_counter;
return true;
}
struct is_play_event
{
template <class EVT,class FSM,class SourceState,class TargetState>
bool operator()(EVT const& evt,FSM&,SourceState& ,TargetState& )
{
bool is_play = boost::any_cast<play>(&evt) != 0;
return is_play;
}
};
struct MyDefer
{
// mark as deferring to avoid stack overflows in certain conditions
typedef int deferring_action;
template <class EVT,class FSM,class SourceState,class TargetState>
void operator()(EVT const& ,FSM& fsm,SourceState& ,TargetState& ) const
{
fsm.defer_event(play());
}
};
typedef player_ p; // makes transition table cleaner
// Transition table for player
struct transition_table : boost::fusion::vector<
// Start Event Next Action Guard
// +---------+-------------+---------+---------------------+----------------------+
a_row < Stopped , play , Playing , &p::start_playback >,
a_row < Stopped , open_close , Open , &p::open_drawer >,
_row < Stopped , stop , Stopped >,
// +---------+-------------+---------+---------------------+----------------------+
g_row < Open , open_close , Empty , &p::can_close_drawer >,
Row < Open , play , none , Defer , none >,
// +---------+-------------+---------+---------------------+----------------------+
a_row < Empty , open_close , Open , &p::open_drawer >,
a_row < Empty , cd_detected , Stopped , &p::store_cd_info >,
Row < Empty , boost::any , none , MyDefer , is_play_event >,
// +---------+-------------+---------+---------------------+----------------------+
a_row < Playing , stop , Stopped , &p::stop_playback >,
a_row < Playing , pause , Paused , &p::pause_playback >,
a_row < Playing , open_close , Open , &p::stop_and_open >,
// +---------+-------------+---------+---------------------+----------------------+
a_row < Paused , end_pause , Playing , &p::resume_playback >,
a_row < Paused , stop , Stopped , &p::stop_playback >,
a_row < Paused , open_close , Open , &p::stop_and_open >,
// +---------+-------------+---------+---------------------+----------------------+
a_row < AllOk , error_found ,ErrorMode, &p::report_error >,
a_row <ErrorMode, end_error ,AllOk , &p::report_end_error >,
_row < AllOk , do_terminate,ErrorTerminate >
// +---------+-------------+---------+---------------------+----------------------+
> {};
// Replaces the default no-transition response.
template <class FSM,class Event>
void no_transition(Event const& , FSM&,int)
{
BOOST_ERROR("no_transition called!");
}
// init counters
template <class Event,class FSM>
void on_entry(Event const&,FSM& fsm)
{
fsm.template get_state<player_::Stopped&>().entry_counter=0;
fsm.template get_state<player_::Stopped&>().exit_counter=0;
fsm.template get_state<player_::Open&>().entry_counter=0;
fsm.template get_state<player_::Open&>().exit_counter=0;
fsm.template get_state<player_::Empty&>().entry_counter=0;
fsm.template get_state<player_::Empty&>().exit_counter=0;
fsm.template get_state<player_::Playing&>().entry_counter=0;
fsm.template get_state<player_::Playing&>().exit_counter=0;
fsm.template get_state<player_::Playing&>().template get_state<player_::Playing::Song1&>().entry_counter=0;
fsm.template get_state<player_::Playing&>().template get_state<player_::Playing::Song1&>().exit_counter=0;
fsm.template get_state<player_::Playing&>().template get_state<player_::Playing::Song2&>().entry_counter=0;
fsm.template get_state<player_::Playing&>().template get_state<player_::Playing::Song2&>().exit_counter=0;
fsm.template get_state<player_::Playing&>().template get_state<player_::Playing::Song3&>().entry_counter=0;
fsm.template get_state<player_::Playing&>().template get_state<player_::Playing::Song3&>().exit_counter=0;
fsm.template get_state<player_::Paused&>().entry_counter=0;
fsm.template get_state<player_::Paused&>().exit_counter=0;
fsm.template get_state<player_::AllOk&>().entry_counter=0;
fsm.template get_state<player_::AllOk&>().exit_counter=0;
fsm.template get_state<player_::ErrorMode&>().entry_counter=0;
fsm.template get_state<player_::ErrorMode&>().exit_counter=0;
fsm.template get_state<player_::ErrorTerminate&>().entry_counter=0;
fsm.template get_state<player_::ErrorTerminate&>().exit_counter=0;
}
};
// Pick a back-end
typedef msm::back11::state_machine<player_> player;
//static char const* const state_names[] = { "Stopped", "Open", "Empty", "Playing", "Paused","AllOk","ErrorMode" };
BOOST_AUTO_TEST_CASE( back11_orthogonal_deferred3_test )
{
player p;
// needed to start the highest-level SM. This will call on_entry and mark the start of the SM
p.start();
// test deferred event
// deferred in Empty and Open, will be handled only after event cd_detected
p.process_event(play());
BOOST_CHECK_MESSAGE(p.current_state()[0] == 2,"Empty should be active"); //Empty
BOOST_CHECK_MESSAGE(p.get_state<player_::Open&>().exit_counter == 0,"Open exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::Playing&>().entry_counter == 0,"Playing entry not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::Empty&>().entry_counter == 1,"Empty entry not called correctly");
//flags
BOOST_CHECK_MESSAGE(p.is_flag_active<CDLoaded>() == false,"CDLoaded should not be active");
p.process_event(open_close());
BOOST_CHECK_MESSAGE(p.current_state()[0] == 1,"Open should be active"); //Open
BOOST_CHECK_MESSAGE(p.get_state<player_::Empty&>().exit_counter == 1,"Empty exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::Open&>().entry_counter == 1,"Open entry not called correctly");
p.process_event(open_close());
BOOST_CHECK_MESSAGE(p.current_state()[0] == 2,"Empty should be active"); //Empty
BOOST_CHECK_MESSAGE(p.get_state<player_::Open&>().exit_counter == 1,"Open exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::Empty&>().entry_counter == 2,"Empty entry not called correctly");
BOOST_CHECK_MESSAGE(p.can_close_drawer_counter == 1,"guard not called correctly");
//deferred event should have been processed
p.process_event(cd_detected("louie, louie"));
BOOST_CHECK_MESSAGE(p.current_state()[0] == 3,"Playing should be active"); //Playing
BOOST_CHECK_MESSAGE(p.get_state<player_::Empty&>().exit_counter == 2,"Empty exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::Stopped&>().entry_counter == 1,"Stopped entry not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::Stopped&>().exit_counter == 1,"Stopped exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::Playing&>().entry_counter == 1,"Playing entry not called correctly");
BOOST_CHECK_MESSAGE(p.start_playback_counter == 1,"action not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::Playing&>().current_state()[0] == 0,"Song1 should be active");
BOOST_CHECK_MESSAGE(
p.get_state<player_::Playing&>().get_state<player_::Playing::Song1&>().entry_counter == 1,
"Song1 entry not called correctly");
//flags
BOOST_CHECK_MESSAGE(p.is_flag_active<PlayingPaused>() == true,"PlayingPaused should be active");
BOOST_CHECK_MESSAGE(p.is_flag_active<FirstSongPlaying>() == true,"FirstSongPlaying should be active");
p.process_event(NextSong());
BOOST_CHECK_MESSAGE(p.current_state()[0] == 3,"Playing should be active"); //Playing
BOOST_CHECK_MESSAGE(p.get_state<player_::Playing&>().current_state()[0] == 1,"Song2 should be active");
BOOST_CHECK_MESSAGE(
p.get_state<player_::Playing&>().get_state<player_::Playing::Song2&>().entry_counter == 1,
"Song2 entry not called correctly");
BOOST_CHECK_MESSAGE(
p.get_state<player_::Playing&>().get_state<player_::Playing::Song1&>().exit_counter == 1,
"Song1 exit not called correctly");
BOOST_CHECK_MESSAGE(
p.get_state<player_::Playing&>().start_next_song_counter == 0,
"submachine action not called correctly");
p.process_event(NextSong());
BOOST_CHECK_MESSAGE(p.current_state()[0] == 3,"Playing should be active"); //Playing
BOOST_CHECK_MESSAGE(p.get_state<player_::Playing&>().current_state()[0] == 2,"Song3 should be active");
BOOST_CHECK_MESSAGE(
p.get_state<player_::Playing&>().get_state<player_::Playing::Song3&>().entry_counter == 1,
"Song3 entry not called correctly");
BOOST_CHECK_MESSAGE(
p.get_state<player_::Playing&>().get_state<player_::Playing::Song2&>().exit_counter == 1,
"Song2 exit not called correctly");
BOOST_CHECK_MESSAGE(
p.get_state<player_::Playing&>().start_next_song_counter == 1,
"submachine action not called correctly");
p.process_event(PreviousSong());
BOOST_CHECK_MESSAGE(p.current_state()[0] == 3,"Playing should be active"); //Playing
BOOST_CHECK_MESSAGE(p.get_state<player_::Playing&>().current_state()[0] == 1,"Song2 should be active");
BOOST_CHECK_MESSAGE(
p.get_state<player_::Playing&>().get_state<player_::Playing::Song2&>().entry_counter == 2,
"Song2 entry not called correctly");
BOOST_CHECK_MESSAGE(
p.get_state<player_::Playing&>().get_state<player_::Playing::Song3&>().exit_counter == 1,
"Song3 exit not called correctly");
BOOST_CHECK_MESSAGE(
p.get_state<player_::Playing&>().start_prev_song_guard_counter == 1,
"submachine guard not called correctly");
//flags
BOOST_CHECK_MESSAGE(p.is_flag_active<PlayingPaused>() == true,"PlayingPaused should be active");
BOOST_CHECK_MESSAGE(p.is_flag_active<FirstSongPlaying>() == false,"FirstSongPlaying should not be active");
p.process_event(pause());
BOOST_CHECK_MESSAGE(p.current_state()[0] == 4,"Paused should be active"); //Paused
BOOST_CHECK_MESSAGE(p.get_state<player_::Playing&>().exit_counter == 1,"Playing exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::Paused&>().entry_counter == 1,"Paused entry not called correctly");
//flags
BOOST_CHECK_MESSAGE(p.is_flag_active<PlayingPaused>() == true,"PlayingPaused should be active");
// go back to Playing
p.process_event(end_pause());
BOOST_CHECK_MESSAGE(p.current_state()[0] == 3,"Playing should be active"); //Playing
BOOST_CHECK_MESSAGE(p.get_state<player_::Paused&>().exit_counter == 1,"Paused exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::Playing&>().entry_counter == 2,"Playing entry not called correctly");
p.process_event(pause());
BOOST_CHECK_MESSAGE(p.current_state()[0] == 4,"Paused should be active"); //Paused
BOOST_CHECK_MESSAGE(p.get_state<player_::Playing&>().exit_counter == 2,"Playing exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::Paused&>().entry_counter == 2,"Paused entry not called correctly");
p.process_event(stop());
BOOST_CHECK_MESSAGE(p.current_state()[0] == 0,"Stopped should be active"); //Stopped
BOOST_CHECK_MESSAGE(p.get_state<player_::Paused&>().exit_counter == 2,"Paused exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::Stopped&>().entry_counter == 2,"Stopped entry not called correctly");
//flags
BOOST_CHECK_MESSAGE(p.is_flag_active<PlayingPaused>() == false,"PlayingPaused should not be active");
BOOST_CHECK_MESSAGE(p.is_flag_active<CDLoaded>() == true,"CDLoaded should be active");
//BOOST_CHECK_MESSAGE(p.is_flag_active<CDLoaded,player::Flag_AND>() == false,"CDLoaded with AND should not be active");
p.process_event(stop());
BOOST_CHECK_MESSAGE(p.current_state()[0] == 0,"Stopped should be active"); //Stopped
BOOST_CHECK_MESSAGE(p.get_state<player_::Stopped&>().exit_counter == 2,"Stopped exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::Stopped&>().entry_counter == 3,"Stopped entry not called correctly");
//test interrupt
BOOST_CHECK_MESSAGE(p.current_state()[1] == 5,"AllOk should be active"); //AllOk
p.process_event(error_found());
BOOST_CHECK_MESSAGE(p.current_state()[1] == 6,"ErrorMode should be active"); //ErrorMode
BOOST_CHECK_MESSAGE(p.get_state<player_::AllOk&>().exit_counter == 1,"AllOk exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::ErrorMode&>().entry_counter == 1,"ErrorMode entry not called correctly");
// try generating more events
p.process_event(play());
BOOST_CHECK_MESSAGE(p.current_state()[1] == 6,"ErrorMode should be active"); //ErrorMode
BOOST_CHECK_MESSAGE(p.get_state<player_::AllOk&>().exit_counter == 1,"AllOk exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::ErrorMode&>().entry_counter == 1,"ErrorMode entry not called correctly");
BOOST_CHECK_MESSAGE(p.current_state()[0] == 0,"Stopped should be active"); //Stopped
BOOST_CHECK_MESSAGE(p.get_state<player_::Stopped&>().exit_counter == 2,"Stopped exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::Stopped&>().entry_counter == 3,"Stopped entry not called correctly");
p.process_event(end_error());
BOOST_CHECK_MESSAGE(p.current_state()[1] == 5,"AllOk should be active"); //AllOk
BOOST_CHECK_MESSAGE(p.get_state<player_::ErrorMode&>().exit_counter == 1,"ErrorMode exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::AllOk&>().entry_counter == 2,"AllOk entry not called correctly");
p.process_event(play());
BOOST_CHECK_MESSAGE(p.current_state()[0] == 3,"Playing should be active"); //Playing
BOOST_CHECK_MESSAGE(p.get_state<player_::Stopped&>().exit_counter == 3,"Stopped exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::Playing&>().entry_counter == 3,"Playing entry not called correctly");
//test terminate
BOOST_CHECK_MESSAGE(p.current_state()[1] == 5,"AllOk should be active"); //AllOk
p.process_event(do_terminate());
BOOST_CHECK_MESSAGE(p.current_state()[1] == 7,"ErrorTerminate should be active"); //ErrorTerminate
BOOST_CHECK_MESSAGE(p.get_state<player_::AllOk&>().exit_counter == 2,"AllOk exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::ErrorTerminate&>().entry_counter == 1,"ErrorTerminate entry not called correctly");
// try generating more events
p.process_event(stop());
BOOST_CHECK_MESSAGE(p.current_state()[1] == 7,"ErrorTerminate should be active"); //ErrorTerminate
BOOST_CHECK_MESSAGE(p.get_state<player_::ErrorTerminate&>().exit_counter == 0,"ErrorTerminate exit not called correctly");
BOOST_CHECK_MESSAGE(p.current_state()[0] == 3,"Playing should be active"); //Playing
BOOST_CHECK_MESSAGE(p.get_state<player_::Playing&>().exit_counter == 2,"Playing exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::Stopped&>().entry_counter == 3,"Stopped entry not called correctly");
p.process_event(end_error());
BOOST_CHECK_MESSAGE(p.current_state()[1] == 7,"ErrorTerminate should be active"); //ErrorTerminate
BOOST_CHECK_MESSAGE(p.current_state()[0] == 3,"Playing should be active"); //Playing
BOOST_CHECK_MESSAGE(p.get_state<player_::Playing&>().exit_counter == 2,"Playing exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::Stopped&>().entry_counter == 3,"Stopped entry not called correctly");
p.process_event(stop());
BOOST_CHECK_MESSAGE(p.current_state()[1] == 7,"ErrorTerminate should be active"); //ErrorTerminate
BOOST_CHECK_MESSAGE(p.current_state()[0] == 3,"Playing should be active"); //Playing
BOOST_CHECK_MESSAGE(p.get_state<player_::Playing&>().exit_counter == 2,"Playing exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::Stopped&>().entry_counter == 3,"Stopped entry not called correctly");
}
}
+1 -1
View File
@@ -14,7 +14,7 @@
#include <boost/msm/front/state_machine_def.hpp>
#include <boost/msm/front/puml/puml.hpp>
#include <PumlCommon.hpp>
#include "PumlCommon.hpp"
#ifndef BOOST_MSM_NONSTANDALONE_TEST
#define BOOST_TEST_MODULE back11_orthogonal_deferred3_with_puml_test
-253
View File
@@ -1,253 +0,0 @@
// 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 <boost/msm/back11/state_machine.hpp>
#include <boost/msm/front/euml/euml.hpp>
#ifndef BOOST_MSM_NONSTANDALONE_TEST
#define BOOST_TEST_MODULE back11_simple_internal_euml_test
#endif
#include <boost/test/unit_test.hpp>
using namespace std;
using namespace boost::msm::front::euml;
namespace msm = boost::msm;
namespace
{
// A "complicated" event type that carries some data.
enum DiskTypeEnum
{
DISK_CD=0,
DISK_DVD=1
};
// events
BOOST_MSM_EUML_EVENT(play)
BOOST_MSM_EUML_EVENT(end_pause)
BOOST_MSM_EUML_EVENT(stop)
BOOST_MSM_EUML_EVENT(pause)
BOOST_MSM_EUML_EVENT(open_close)
BOOST_MSM_EUML_EVENT(internal_evt)
BOOST_MSM_EUML_EVENT(to_ignore)
// A "complicated" event type that carries some data.
BOOST_MSM_EUML_DECLARE_ATTRIBUTE(std::string,cd_name)
BOOST_MSM_EUML_DECLARE_ATTRIBUTE(DiskTypeEnum,cd_type)
BOOST_MSM_EUML_ATTRIBUTES((attributes_ << cd_name << cd_type ), cd_detected_attributes)
BOOST_MSM_EUML_EVENT_WITH_ATTRIBUTES(cd_detected,cd_detected_attributes)
//states
BOOST_MSM_EUML_DECLARE_ATTRIBUTE(unsigned int,entry_counter)
BOOST_MSM_EUML_DECLARE_ATTRIBUTE(unsigned int,exit_counter)
BOOST_MSM_EUML_STATE(( ++state_(entry_counter),++state_(exit_counter),attributes_ << entry_counter << exit_counter),Open)
BOOST_MSM_EUML_STATE(( ++state_(entry_counter),++state_(exit_counter),attributes_ << entry_counter << exit_counter),Stopped)
BOOST_MSM_EUML_STATE(( ++state_(entry_counter),++state_(exit_counter),attributes_ << entry_counter << exit_counter),Playing)
BOOST_MSM_EUML_STATE(( ++state_(entry_counter),++state_(exit_counter),attributes_ << entry_counter << exit_counter),Paused)
BOOST_MSM_EUML_DECLARE_ATTRIBUTE(unsigned int,empty_internal_guard_counter)
BOOST_MSM_EUML_DECLARE_ATTRIBUTE(unsigned int,empty_internal_action_counter)
BOOST_MSM_EUML_ACTION(internal_guard_fct)
{
template <class FSM,class EVT,class SourceState,class TargetState>
bool operator()(EVT const&, FSM& ,SourceState& src,TargetState& )
{
++src.get_attribute(empty_internal_guard_counter);
return false;
}
};
BOOST_MSM_EUML_DECLARE_STATE((++state_(entry_counter),++state_(exit_counter),
attributes_ << entry_counter << exit_counter
<< empty_internal_guard_counter << empty_internal_action_counter),Empty_def)
// derive to be able to add an internal transition table
struct Empty_impl : public Empty_def
{
Empty_impl(){}
BOOST_MSM_EUML_DECLARE_INTERNAL_TRANSITION_TABLE((
internal_evt [internal_guard_fct] / ++source_(empty_internal_action_counter)
))
};
// declare an instance for the stt as we are manually declaring a state
Empty_impl const Empty;
//fsm
BOOST_MSM_EUML_DECLARE_ATTRIBUTE(unsigned int,start_playback_counter)
BOOST_MSM_EUML_DECLARE_ATTRIBUTE(unsigned int,can_close_drawer_counter)
BOOST_MSM_EUML_DECLARE_ATTRIBUTE(unsigned int,internal_action_counter)
BOOST_MSM_EUML_DECLARE_ATTRIBUTE(unsigned int,internal_guard_counter)
BOOST_MSM_EUML_ACTION(No_Transition)
{
template <class FSM,class Event>
void operator()(Event const&,FSM&,int)
{
BOOST_FAIL("no_transition called!");
}
};
BOOST_MSM_EUML_ACTION(good_disk_format)
{
template <class FSM,class EVT,class SourceState,class TargetState>
bool operator()(EVT const& evt,FSM&,SourceState& ,TargetState& )
{
if (evt.get_attribute(cd_type)!=DISK_CD)
{
return false;
}
return true;
}
};
BOOST_MSM_EUML_ACTION(internal_guard)
{
template <class FSM,class EVT,class SourceState,class TargetState>
bool operator()(EVT const&,FSM& fsm,SourceState& ,TargetState& )
{
++fsm.get_attribute(internal_guard_counter);
return false;
}
};
BOOST_MSM_EUML_ACTION(internal_guard2)
{
template <class FSM,class EVT,class SourceState,class TargetState>
bool operator()(EVT const&,FSM& fsm,SourceState& ,TargetState& )
{
++fsm.get_attribute(internal_guard_counter);
return true;
}
};
BOOST_MSM_EUML_TRANSITION_TABLE((
Playing == Stopped + play / ++fsm_(start_playback_counter) ,
Playing == Paused + end_pause ,
// +------------------------------------------------------------------------------+
Empty == Open + open_close / ++fsm_(can_close_drawer_counter),
Empty + to_ignore ,
Empty + internal_evt [internal_guard2] / ++fsm_(internal_action_counter) ,
Empty + cd_detected [internal_guard] ,
// +------------------------------------------------------------------------------+
Open == Empty + open_close ,
Open == Paused + open_close ,
Open == Stopped + open_close ,
Open == Playing + open_close ,
// +------------------------------------------------------------------------------+
Paused == Playing + pause ,
// +------------------------------------------------------------------------------+
Stopped == Playing + stop ,
Stopped == Paused + stop ,
Stopped == Empty + cd_detected [good_disk_format] ,
Stopped == Stopped + stop
// +------------------------------------------------------------------------------+
),transition_table)
BOOST_MSM_EUML_DECLARE_STATE_MACHINE(( transition_table, //STT
init_ << Empty, // Init State
no_action, // Entry
no_action, // Exit
attributes_ << start_playback_counter << can_close_drawer_counter
<< internal_action_counter << internal_guard_counter, // Attributes
configure_ << no_configure_, // configuration
No_Transition // no_transition handler
),
player_) //fsm name
typedef msm::back11::state_machine<player_> player;
// static char const* const state_names[] = { "Stopped", "Paused", "Open", "Empty", "Playing" };
BOOST_AUTO_TEST_CASE( back11_simple_internal_euml_test )
{
player p;
p.start();
BOOST_CHECK_MESSAGE(p.get_state<Empty_impl&>().get_attribute(entry_counter) == 1,
"Empty entry not called correctly");
// internal events
p.process_event(to_ignore);
p.process_event(internal_evt);
BOOST_CHECK_MESSAGE(p.get_attribute(internal_action_counter) == 1,"Internal action not called correctly");
BOOST_CHECK_MESSAGE(p.get_attribute(internal_guard_counter) == 1,"Internal guard not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<Empty_impl&>().get_attribute(empty_internal_action_counter) == 0,
"Empty internal action not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<Empty_impl&>().get_attribute(empty_internal_guard_counter) == 1,
"Empty internal guard not called correctly");
p.process_event(open_close());
BOOST_CHECK_MESSAGE(p.current_state()[0] == 2,"Open should be active"); //Open
BOOST_CHECK_MESSAGE(p.get_state<Empty_impl&>().get_attribute(exit_counter) == 1,
"Empty exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<Empty_impl&>().get_attribute(entry_counter) == 1,
"Open entry not called correctly");
p.process_event(open_close());
BOOST_CHECK_MESSAGE(p.current_state()[0] == 3,"Empty should be active"); //Empty
BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(Open)&>().get_attribute(exit_counter) == 1,
"Open exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<Empty_impl&>().get_attribute(entry_counter) == 2,
"Empty entry not called correctly");
BOOST_CHECK_MESSAGE(p.get_attribute(can_close_drawer_counter) == 1,"guard not called correctly");
p.process_event(
cd_detected("louie, louie",DISK_DVD));
BOOST_CHECK_MESSAGE(p.current_state()[0] == 3,"Empty should be active"); //Empty
BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(Open)&>().get_attribute(exit_counter) == 1,
"Open exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<Empty_impl&>().get_attribute(entry_counter) == 2,
"Empty entry not called correctly");
p.process_event(
cd_detected("louie, louie",DISK_CD));
p.process_event(play);
BOOST_CHECK_MESSAGE(p.current_state()[0] == 4,"Playing should be active"); //Playing
BOOST_CHECK_MESSAGE(p.get_state<Empty_impl&>().get_attribute(exit_counter) == 2,
"Empty exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(Stopped)&>().get_attribute(entry_counter) == 1,
"Stopped entry not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(Stopped)&>().get_attribute(exit_counter) == 1,
"Stopped exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(Playing)&>().get_attribute(entry_counter) == 1,
"Playing entry not called correctly");
BOOST_CHECK_MESSAGE(p.get_attribute(start_playback_counter) == 1,"action not called correctly");
p.process_event(pause());
BOOST_CHECK_MESSAGE(p.current_state()[0] == 1,"Paused should be active"); //Paused
BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(Playing)&>().get_attribute(exit_counter) == 1,
"Playing exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(Paused)&>().get_attribute(entry_counter) == 1,
"Paused entry not called correctly");
// go back to Playing
p.process_event(end_pause());
BOOST_CHECK_MESSAGE(p.current_state()[0] == 4,"Playing should be active"); //Playing
BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(Paused)&>().get_attribute(exit_counter) == 1,
"Paused exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(Playing)&>().get_attribute(entry_counter) == 2,
"Playing entry not called correctly");
p.process_event(pause());
BOOST_CHECK_MESSAGE(p.current_state()[0] == 1,"Paused should be active"); //Paused
BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(Playing)&>().get_attribute(exit_counter) == 2,
"Playing exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(Paused)&>().get_attribute(entry_counter) == 2,
"Paused entry not called correctly");
p.process_event(stop());
BOOST_CHECK_MESSAGE(p.current_state()[0] == 0,"Stopped should be active"); //Stopped
BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(Paused)&>().get_attribute(exit_counter) == 2,
"Paused exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(Stopped)&>().get_attribute(entry_counter) == 2,
"Stopped entry not called correctly");
p.process_event(stop());
BOOST_CHECK_MESSAGE(p.current_state()[0] == 0,"Stopped should be active"); //Stopped
BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(Stopped)&>().get_attribute(exit_counter) == 2,
"Stopped exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(Stopped)&>().get_attribute(entry_counter) == 3,
"Stopped entry not called correctly");
}
}
-331
View File
@@ -1,331 +0,0 @@
// 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)
// back-end
#include <boost/msm/back11/state_machine.hpp>
//front-end
#include <boost/msm/front/state_machine_def.hpp>
#include <boost/msm/front/functor_row.hpp>
#include <boost/msm/front/euml/common.hpp>
#ifndef BOOST_MSM_NONSTANDALONE_TEST
#define BOOST_TEST_MODULE back11_simple_internal_functors_test
#endif
#include <boost/test/unit_test.hpp>
using namespace std;
namespace msm = boost::msm;
using namespace msm::front;
namespace mpl = boost::mpl;
namespace
{
// events
struct play {};
struct end_pause {};
struct stop {};
struct pause {};
struct open_close {};
struct internal_evt {};
struct to_ignore {};
// A "complicated" event type that carries some data.
enum DiskTypeEnum
{
DISK_CD=0,
DISK_DVD=1
};
struct cd_detected
{
cd_detected(std::string name, DiskTypeEnum diskType)
: name(name),
disc_type(diskType)
{}
std::string name;
DiskTypeEnum disc_type;
};
// front-end: define the FSM structure
struct player_ : public msm::front::state_machine_def<player_>
{
unsigned int start_playback_counter;
unsigned int can_close_drawer_counter;
unsigned int internal_action_counter;
unsigned int internal_guard_counter;
player_():
start_playback_counter(0),
can_close_drawer_counter(0),
internal_action_counter(0),
internal_guard_counter(0)
{}
// The list of FSM states
struct Empty : public msm::front::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;
int exit_counter;
unsigned int empty_internal_guard_counter;
unsigned int empty_internal_action_counter;
struct internal_guard_fct
{
template <class EVT,class FSM,class SourceState,class TargetState>
bool operator()(EVT const& ,FSM&,SourceState& src,TargetState& )
{
++src.empty_internal_guard_counter;
return false;
}
};
struct internal_action_fct
{
template <class EVT,class FSM,class SourceState,class TargetState>
void operator()(EVT const& ,FSM& ,SourceState& src,TargetState& )
{
++src.empty_internal_action_counter;
}
};
// Transition table for Empty
struct internal_transition_table : boost::fusion::vector<
// Start Event Next Action Guard
Internal < internal_evt , internal_action_fct ,internal_guard_fct >
// +---------+-------------+---------+---------------------+----------------------+
> {};
};
struct Open : public msm::front::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;
int exit_counter;
};
// sm_ptr still supported but deprecated as functors are a much better way to do the same thing
struct Stopped : public msm::front::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;
int exit_counter;
};
struct Playing : public msm::front::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;
int exit_counter;
};
// state not defining any entry or exit
struct Paused : public msm::front::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;
int exit_counter;
};
// the initial state of the player SM. Must be defined
typedef Empty initial_state;
// transition actions
void start_playback(play const&) {++start_playback_counter; }
void open_drawer(open_close const&) { }
void store_cd_info(cd_detected const&) { }
void stop_playback(stop const&) { }
void pause_playback(pause const&) { }
void resume_playback(end_pause const&) { }
void stop_and_open(open_close const&) { }
void stopped_again(stop const&){}
struct internal_action
{
template <class EVT,class FSM,class SourceState,class TargetState>
void operator()(EVT const& ,FSM& fsm,SourceState& ,TargetState& )
{
++fsm.internal_action_counter;
}
};
struct internal_guard
{
template <class EVT,class FSM,class SourceState,class TargetState>
bool operator()(EVT const& ,FSM& fsm,SourceState& ,TargetState& )
{
++fsm.internal_guard_counter;
return false;
}
};
struct internal_guard2
{
template <class EVT,class FSM,class SourceState,class TargetState>
bool operator()(EVT const& ,FSM& fsm,SourceState& ,TargetState& )
{
++fsm.internal_guard_counter;
return true;
}
};
// guard conditions
bool good_disk_format(cd_detected const& evt)
{
// to test a guard condition, let's say we understand only CDs, not DVD
if (evt.disc_type != DISK_CD)
{
return false;
}
return true;
}
bool can_close_drawer(open_close const&)
{
++can_close_drawer_counter;
return true;
}
typedef player_ p; // makes transition table cleaner
// Transition table for player
struct transition_table : boost::fusion::vector<
// Start Event Next Action Guard
// +---------+-------------+---------+---------------------+----------------------+
a_row < Stopped , play , Playing , &p::start_playback >,
a_row < Stopped , open_close , Open , &p::open_drawer >,
_row < Stopped , stop , Stopped >,
// +---------+-------------+---------+---------------------+----------------------+
g_row < Open , open_close , Empty , &p::can_close_drawer >,
// +---------+-------------+---------+---------------------+----------------------+
a_row < Empty , open_close , Open , &p::open_drawer >,
row < Empty , cd_detected , Stopped , &p::store_cd_info ,&p::good_disk_format >,
Row < Empty , internal_evt, none , internal_action ,internal_guard2 >,
Row < Empty , to_ignore , none , none , none >,
Row < Empty , cd_detected , none , none ,internal_guard >,
// +---------+-------------+---------+---------------------+----------------------+
a_row < Playing , stop , Stopped , &p::stop_playback >,
a_row < Playing , pause , Paused , &p::pause_playback >,
a_row < Playing , open_close , Open , &p::stop_and_open >,
// +---------+-------------+---------+---------------------+----------------------+
a_row < Paused , end_pause , Playing , &p::resume_playback >,
a_row < Paused , stop , Stopped , &p::stop_playback >,
a_row < Paused , open_close , Open , &p::stop_and_open >
// +---------+-------------+---------+---------------------+----------------------+
> {};
// Replaces the default no-transition response.
template <class FSM,class Event>
void no_transition(Event const&, FSM&,int)
{
BOOST_FAIL("no_transition called!");
}
// init counters
template <class Event,class FSM>
void on_entry(Event const&,FSM& fsm)
{
fsm.template get_state<player_::Stopped&>().entry_counter=0;
fsm.template get_state<player_::Stopped&>().exit_counter=0;
fsm.template get_state<player_::Open&>().entry_counter=0;
fsm.template get_state<player_::Open&>().exit_counter=0;
fsm.template get_state<player_::Empty&>().entry_counter=0;
fsm.template get_state<player_::Empty&>().exit_counter=0;
fsm.template get_state<player_::Empty&>().empty_internal_guard_counter=0;
fsm.template get_state<player_::Empty&>().empty_internal_action_counter=0;
fsm.template get_state<player_::Playing&>().entry_counter=0;
fsm.template get_state<player_::Playing&>().exit_counter=0;
fsm.template get_state<player_::Paused&>().entry_counter=0;
fsm.template get_state<player_::Paused&>().exit_counter=0;
}
};
// Pick a back-end
typedef msm::back11::state_machine<player_> player;
// static char const* const state_names[] = { "Stopped", "Open", "Empty", "Playing", "Paused" };
BOOST_AUTO_TEST_CASE( back11_simple_internal_functors_test )
{
player p;
p.start();
BOOST_CHECK_MESSAGE(p.get_state<player_::Empty&>().entry_counter == 1,"Empty entry not called correctly");
// internal events
p.process_event(to_ignore());
p.process_event(internal_evt());
BOOST_CHECK_MESSAGE(p.internal_action_counter == 1,"Internal action not called correctly");
BOOST_CHECK_MESSAGE(p.internal_guard_counter == 1,"Internal guard not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::Empty&>().empty_internal_action_counter == 0,"Empty internal action not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::Empty&>().empty_internal_guard_counter == 1,"Empty internal guard not called correctly");
p.process_event(open_close());
BOOST_CHECK_MESSAGE(p.current_state()[0] == 1,"Open should be active"); //Open
BOOST_CHECK_MESSAGE(p.get_state<player_::Empty&>().exit_counter == 1,"Empty exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::Open&>().entry_counter == 1,"Open entry not called correctly");
p.process_event(open_close());
BOOST_CHECK_MESSAGE(p.current_state()[0] == 2,"Empty should be active"); //Empty
BOOST_CHECK_MESSAGE(p.get_state<player_::Open&>().exit_counter == 1,"Open exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::Empty&>().entry_counter == 2,"Empty entry not called correctly");
BOOST_CHECK_MESSAGE(p.can_close_drawer_counter == 1,"guard not called correctly");
p.process_event(
cd_detected("louie, louie",DISK_DVD));
BOOST_CHECK_MESSAGE(p.current_state()[0] == 2,"Empty should be active"); //Empty
BOOST_CHECK_MESSAGE(p.get_state<player_::Open&>().exit_counter == 1,"Open exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::Empty&>().entry_counter == 2,"Empty entry not called correctly");
BOOST_CHECK_MESSAGE(p.internal_guard_counter == 2,"Internal guard not called correctly");
p.process_event(
cd_detected("louie, louie",DISK_CD));
BOOST_CHECK_MESSAGE(p.current_state()[0] == 0,"Stopped should be active"); //Stopped
BOOST_CHECK_MESSAGE(p.get_state<player_::Empty&>().exit_counter == 2,"Empty exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::Stopped&>().entry_counter == 1,"Stopped entry not called correctly");
BOOST_CHECK_MESSAGE(p.internal_guard_counter == 3,"Internal guard not called correctly");
p.process_event(play());
BOOST_CHECK_MESSAGE(p.current_state()[0] == 3,"Playing should be active"); //Playing
BOOST_CHECK_MESSAGE(p.get_state<player_::Stopped&>().exit_counter == 1,"Stopped exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::Playing&>().entry_counter == 1,"Playing entry not called correctly");
BOOST_CHECK_MESSAGE(p.start_playback_counter == 1,"action not called correctly");
p.process_event(pause());
BOOST_CHECK_MESSAGE(p.current_state()[0] == 4,"Paused should be active"); //Paused
BOOST_CHECK_MESSAGE(p.get_state<player_::Playing&>().exit_counter == 1,"Playing exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::Paused&>().entry_counter == 1,"Paused entry not called correctly");
// go back to Playing
p.process_event(end_pause());
BOOST_CHECK_MESSAGE(p.current_state()[0] == 3,"Playing should be active"); //Playing
BOOST_CHECK_MESSAGE(p.get_state<player_::Paused&>().exit_counter == 1,"Paused exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::Playing&>().entry_counter == 2,"Playing entry not called correctly");
p.process_event(pause());
BOOST_CHECK_MESSAGE(p.current_state()[0] == 4,"Paused should be active"); //Paused
BOOST_CHECK_MESSAGE(p.get_state<player_::Playing&>().exit_counter == 2,"Playing exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::Paused&>().entry_counter == 2,"Paused entry not called correctly");
p.process_event(stop());
BOOST_CHECK_MESSAGE(p.current_state()[0] == 0,"Stopped should be active"); //Stopped
BOOST_CHECK_MESSAGE(p.get_state<player_::Paused&>().exit_counter == 2,"Paused exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::Stopped&>().entry_counter == 2,"Stopped entry not called correctly");
p.process_event(stop());
BOOST_CHECK_MESSAGE(p.current_state()[0] == 0,"Stopped should be active"); //Stopped
BOOST_CHECK_MESSAGE(p.get_state<player_::Stopped&>().exit_counter == 2,"Stopped exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::Stopped&>().entry_counter == 3,"Stopped entry not called correctly");
}
}
-256
View File
@@ -1,256 +0,0 @@
// 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)
// back-end
#include <boost/msm/back11/state_machine.hpp>
//front-end
#include <boost/msm/front/state_machine_def.hpp>
#ifndef BOOST_MSM_NONSTANDALONE_TEST
#define BOOST_TEST_MODULE back11_simple_machine_test
#endif
#include <boost/test/unit_test.hpp>
namespace msm = boost::msm;
namespace mpl = boost::mpl;
namespace
{
// events
struct play {};
struct end_pause {};
struct stop {};
struct pause {};
struct open_close {};
// A "complicated" event type that carries some data.
enum DiskTypeEnum
{
DISK_CD=0,
DISK_DVD=1
};
struct cd_detected
{
cd_detected(std::string name, DiskTypeEnum diskType)
: name(name),
disc_type(diskType)
{}
std::string name;
DiskTypeEnum disc_type;
};
// front-end: define the FSM structure
struct player_ : public msm::front::state_machine_def<player_>
{
unsigned int start_playback_counter;
unsigned int can_close_drawer_counter;
player_():
start_playback_counter(0),
can_close_drawer_counter(0)
{}
// The list of FSM states
struct Empty : public msm::front::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;
int exit_counter;
};
struct Open : public msm::front::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;
int exit_counter;
};
// sm_ptr still supported but deprecated as functors are a much better way to do the same thing
struct Stopped : public msm::front::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;
int exit_counter;
};
struct Playing : public msm::front::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;
int exit_counter;
};
// state not defining any entry or exit
struct Paused : public msm::front::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;
int exit_counter;
};
// the initial state of the player SM. Must be defined
typedef Empty initial_state;
// transition actions
void start_playback(play const&) {++start_playback_counter; }
void open_drawer(open_close const&) { }
void store_cd_info(cd_detected const&) { }
void stop_playback(stop const&) { }
void pause_playback(pause const&) { }
void resume_playback(end_pause const&) { }
void stop_and_open(open_close const&) { }
void stopped_again(stop const&){}
// guard conditions
bool good_disk_format(cd_detected const& evt)
{
// to test a guard condition, let's say we understand only CDs, not DVD
if (evt.disc_type != DISK_CD)
{
return false;
}
return true;
}
bool can_close_drawer(open_close const&)
{
++can_close_drawer_counter;
return true;
}
typedef player_ p; // makes transition table cleaner
// Transition table for player
struct transition_table : boost::fusion::vector<
// Start Event Next Action Guard
// +---------+-------------+---------+---------------------+----------------------+
a_row < Stopped , play , Playing , &p::start_playback >,
a_row < Stopped , open_close , Open , &p::open_drawer >,
_row < Stopped , stop , Stopped >,
// +---------+-------------+---------+---------------------+----------------------+
g_row < Open , open_close , Empty , &p::can_close_drawer >,
// +---------+-------------+---------+---------------------+----------------------+
a_row < Empty , open_close , Open , &p::open_drawer >,
row < Empty , cd_detected , Stopped , &p::store_cd_info ,&p::good_disk_format >,
// +---------+-------------+---------+---------------------+----------------------+
a_row < Playing , stop , Stopped , &p::stop_playback >,
a_row < Playing , pause , Paused , &p::pause_playback >,
a_row < Playing , open_close , Open , &p::stop_and_open >,
// +---------+-------------+---------+---------------------+----------------------+
a_row < Paused , end_pause , Playing , &p::resume_playback >,
a_row < Paused , stop , Stopped , &p::stop_playback >,
a_row < Paused , open_close , Open , &p::stop_and_open >
// +---------+-------------+---------+---------------------+----------------------+
> {};
// Replaces the default no-transition response.
template <class FSM,class Event>
void no_transition(Event const& , FSM&,int)
{
BOOST_FAIL("no_transition called!");
}
// init counters
template <class Event,class FSM>
void on_entry(Event const&,FSM& fsm)
{
fsm.template get_state<player_::Stopped&>().entry_counter=0;
fsm.template get_state<player_::Stopped&>().exit_counter=0;
fsm.template get_state<player_::Open&>().entry_counter=0;
fsm.template get_state<player_::Open&>().exit_counter=0;
fsm.template get_state<player_::Empty&>().entry_counter=0;
fsm.template get_state<player_::Empty&>().exit_counter=0;
fsm.template get_state<player_::Playing&>().entry_counter=0;
fsm.template get_state<player_::Playing&>().exit_counter=0;
fsm.template get_state<player_::Paused&>().entry_counter=0;
fsm.template get_state<player_::Paused&>().exit_counter=0;
}
};
// Pick a back-end
typedef msm::back11::state_machine<player_> player;
// static char const* const state_names[] = { "Stopped", "Open", "Empty", "Playing", "Paused" };
BOOST_AUTO_TEST_CASE( back11_simple_machine_test )
{
player p;
p.start();
BOOST_CHECK_MESSAGE(p.get_state<player_::Empty&>().entry_counter == 1,"Empty entry not called correctly");
p.process_event(open_close());
BOOST_CHECK_MESSAGE(p.current_state()[0] == 1,"Open should be active"); //Open
BOOST_CHECK_MESSAGE(p.get_state<player_::Empty&>().exit_counter == 1,"Empty exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::Open&>().entry_counter == 1,"Open entry not called correctly");
p.process_event(open_close());
BOOST_CHECK_MESSAGE(p.current_state()[0] == 2,"Empty should be active"); //Empty
BOOST_CHECK_MESSAGE(p.get_state<player_::Open&>().exit_counter == 1,"Open exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::Empty&>().entry_counter == 2,"Empty entry not called correctly");
BOOST_CHECK_MESSAGE(p.can_close_drawer_counter == 1,"guard not called correctly");
p.process_event(
cd_detected("louie, louie",DISK_DVD));
BOOST_CHECK_MESSAGE(p.current_state()[0] == 2,"Empty should be active"); //Empty
BOOST_CHECK_MESSAGE(p.get_state<player_::Open&>().exit_counter == 1,"Open exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::Empty&>().entry_counter == 2,"Empty entry not called correctly");
p.process_event(
cd_detected("louie, louie",DISK_CD));
BOOST_CHECK_MESSAGE(p.current_state()[0] == 0,"Stopped should be active"); //Stopped
BOOST_CHECK_MESSAGE(p.get_state<player_::Empty&>().exit_counter == 2,"Empty exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::Stopped&>().entry_counter == 1,"Stopped entry not called correctly");
p.process_event(play());
BOOST_CHECK_MESSAGE(p.current_state()[0] == 3,"Playing should be active"); //Playing
BOOST_CHECK_MESSAGE(p.get_state<player_::Stopped&>().exit_counter == 1,"Stopped exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::Playing&>().entry_counter == 1,"Playing entry not called correctly");
BOOST_CHECK_MESSAGE(p.start_playback_counter == 1,"action not called correctly");
p.process_event(pause());
BOOST_CHECK_MESSAGE(p.current_state()[0] == 4,"Paused should be active"); //Paused
BOOST_CHECK_MESSAGE(p.get_state<player_::Playing&>().exit_counter == 1,"Playing exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::Paused&>().entry_counter == 1,"Paused entry not called correctly");
// go back to Playing
p.process_event(end_pause());
BOOST_CHECK_MESSAGE(p.current_state()[0] == 3,"Playing should be active"); //Playing
BOOST_CHECK_MESSAGE(p.get_state<player_::Paused&>().exit_counter == 1,"Paused exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::Playing&>().entry_counter == 2,"Playing entry not called correctly");
p.process_event(pause());
BOOST_CHECK_MESSAGE(p.current_state()[0] == 4,"Paused should be active"); //Paused
BOOST_CHECK_MESSAGE(p.get_state<player_::Playing&>().exit_counter == 2,"Playing exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::Paused&>().entry_counter == 2,"Paused entry not called correctly");
p.process_event(stop());
BOOST_CHECK_MESSAGE(p.current_state()[0] == 0,"Stopped should be active"); //Stopped
BOOST_CHECK_MESSAGE(p.get_state<player_::Paused&>().exit_counter == 2,"Paused exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::Stopped&>().entry_counter == 2,"Stopped entry not called correctly");
p.process_event(stop());
BOOST_CHECK_MESSAGE(p.current_state()[0] == 0,"Stopped should be active"); //Stopped
BOOST_CHECK_MESSAGE(p.get_state<player_::Stopped&>().exit_counter == 2,"Stopped exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::Stopped&>().entry_counter == 3,"Stopped entry not called correctly");
}
}
-367
View File
@@ -1,367 +0,0 @@
// 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 <boost/fusion/adapted/std_tuple.hpp>
#include <boost/fusion/include/std_tuple.hpp>
// back-end
#include <boost/msm/back11/state_machine.hpp>
//front-end
#include <boost/msm/front/state_machine_def.hpp>
// functors
#include <boost/msm/front/functor_row.hpp>
// for And_ operator
#include <boost/msm/front/operator.hpp>
#ifndef BOOST_MSM_NONSTANDALONE_TEST
#define BOOST_TEST_MODULE back11_simple_with_functors_test
#endif
#include <boost/test/unit_test.hpp>
using namespace std;
namespace msm = boost::msm;
namespace mpl = boost::mpl;
using namespace msm::front;
namespace
{
// events
struct play {int cpt_ = 0;};
struct end_pause {int cpt_ = 0;};
struct stop {};
struct pause {};
struct open_close {};
// A "complicated" event type that carries some data.
enum DiskTypeEnum
{
DISK_CD=0,
DISK_DVD=1
};
struct cd_detected
{
cd_detected(std::string name, DiskTypeEnum diskType)
: name(name),
disc_type(diskType)
{}
std::string name;
DiskTypeEnum disc_type;
};
// front-end: define the FSM structure
struct player_ : public msm::front::state_machine_def<player_>
{
unsigned int start_playback_counter;
unsigned int can_close_drawer_counter;
unsigned int test_fct_counter;
player_():
start_playback_counter(0),
can_close_drawer_counter(0),
test_fct_counter(0)
{}
// The list of FSM states
struct Empty : public msm::front::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;
int exit_counter;
};
struct Open : public msm::front::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;
int exit_counter;
};
// sm_ptr still supported but deprecated as functors are a much better way to do the same thing
struct Stopped : public msm::front::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;
int exit_counter;
};
struct Playing : public msm::front::state<>
{
template <class Event,class FSM>
void on_entry(Event const& e,FSM& )
{
++entry_counter;
event_counter = e.cpt_;
}
template <class Event,class FSM>
void on_exit(Event const&,FSM& ) {++exit_counter;}
int entry_counter;
int exit_counter;
int event_counter=0;
};
struct Paused : public msm::front::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;
int exit_counter;
};
// the initial state of the player SM. Must be defined
typedef Empty initial_state;
// transition actions
struct TestFct
{
template <class EVT,class FSM,class SourceState,class TargetState>
void operator()(EVT& e, FSM& fsm,SourceState& ,TargetState& )
{
++e.cpt_;
++fsm.test_fct_counter;
}
};
struct start_playback
{
template <class EVT,class FSM,class SourceState,class TargetState>
void operator()(EVT const& ,FSM& fsm,SourceState& ,TargetState& )
{
++fsm.start_playback_counter;
}
};
struct open_drawer
{
template <class EVT,class FSM,class SourceState,class TargetState>
void operator()(EVT const& ,FSM& ,SourceState& ,TargetState& )
{
}
};
struct close_drawer
{
template <class EVT,class FSM,class SourceState,class TargetState>
void operator()(EVT const& ,FSM& ,SourceState& ,TargetState& )
{
}
};
struct store_cd_info
{
template <class EVT,class FSM,class SourceState,class TargetState>
void operator()(EVT const&,FSM& fsm ,SourceState& ,TargetState& )
{
fsm.process_event(play());
}
};
struct stop_playback
{
template <class EVT,class FSM,class SourceState,class TargetState>
void operator()(EVT const& ,FSM& ,SourceState& ,TargetState& )
{
}
};
struct pause_playback
{
template <class EVT,class FSM,class SourceState,class TargetState>
void operator()(EVT const& ,FSM& ,SourceState& ,TargetState& )
{
}
};
struct resume_playback
{
template <class EVT,class FSM,class SourceState,class TargetState>
void operator()(EVT& e,FSM& ,SourceState& ,TargetState& )
{
++e.cpt_;
}
};
struct stop_and_open
{
template <class EVT,class FSM,class SourceState,class TargetState>
void operator()(EVT const& ,FSM& ,SourceState& ,TargetState& )
{
}
};
struct stopped_again
{
template <class EVT,class FSM,class SourceState,class TargetState>
void operator()(EVT const& ,FSM& ,SourceState& ,TargetState& )
{
}
};
// guard conditions
struct DummyGuard
{
template <class EVT,class FSM,class SourceState,class TargetState>
bool operator()(EVT const&,FSM&,SourceState&,TargetState&)
{
return true;
}
};
struct good_disk_format
{
template <class EVT,class FSM,class SourceState,class TargetState>
bool operator()(EVT& evt ,FSM&,SourceState& ,TargetState& )
{
// to test a guard condition, let's say we understand only CDs, not DVD
if (evt.disc_type != DISK_CD)
{
return false;
}
return true;
}
};
struct always_true
{
template <class EVT,class FSM,class SourceState,class TargetState>
bool operator()(EVT const& ,FSM&,SourceState& ,TargetState& )
{
return true;
}
};
struct can_close_drawer
{
template <class EVT,class FSM,class SourceState,class TargetState>
bool operator()(EVT const& ,FSM& fsm,SourceState& ,TargetState& )
{
++fsm.can_close_drawer_counter;
return true;
}
};
typedef player_ p; // makes transition table cleaner
// Transition table for player
struct transition_table : boost::fusion::vector<
// Start Event Next Action Guard
// +---------+-------------+---------+---------------------+----------------------+
Row < Stopped , play , Playing , ActionSequence_
<boost::fusion::vector<
TestFct,start_playback> >
, DummyGuard >,
Row < Stopped , open_close , Open , open_drawer , none >,
Row < Stopped , stop , Stopped , none , none >,
// +---------+-------------+---------+---------------------------+----------------------+
Row < Open , open_close , Empty , close_drawer , can_close_drawer >,
// +---------+-------------+---------+---------------------------+----------------------+
Row < Empty , open_close , Open , open_drawer , none >,
Row < Empty , cd_detected , Stopped , store_cd_info , And_<good_disk_format,
always_true> >,
// +---------+-------------+---------+---------------------------+----------------------+
Row < Playing , stop , Stopped , stop_playback , none >,
Row < Playing , pause , Paused , pause_playback , none >,
Row < Playing , open_close , Open , stop_and_open , none >,
// +---------+-------------+---------+---------------------------+----------------------+
Row < Paused , end_pause , Playing , resume_playback , none >,
Row < Paused , stop , Stopped , stop_playback , none >,
Row < Paused , open_close , Open , stop_and_open , none >
// +---------+-------------+---------+---------------------+----------------------+
>/*>::type*/ {};
// Replaces the default no-transition response.
template <class FSM,class Event>
void no_transition(Event const&, FSM&,int)
{
BOOST_FAIL("no_transition called!");
}
// init counters
template <class Event,class FSM>
void on_entry(Event const&,FSM& fsm)
{
fsm.template get_state<player_::Stopped&>().entry_counter=0;
fsm.template get_state<player_::Stopped&>().exit_counter=0;
fsm.template get_state<player_::Open&>().entry_counter=0;
fsm.template get_state<player_::Open&>().exit_counter=0;
fsm.template get_state<player_::Empty&>().entry_counter=0;
fsm.template get_state<player_::Empty&>().exit_counter=0;
fsm.template get_state<player_::Playing&>().entry_counter=0;
fsm.template get_state<player_::Playing&>().exit_counter=0;
fsm.template get_state<player_::Paused&>().entry_counter=0;
fsm.template get_state<player_::Paused&>().exit_counter=0;
}
};
// Pick a back-end
typedef msm::back11::state_machine<player_> player;
// static char const* const state_names[] = { "Stopped", "Open", "Empty", "Playing", "Paused" };
BOOST_AUTO_TEST_CASE( back11_simple_with_functors_test )
{
player p;
p.start();
BOOST_CHECK_MESSAGE(p.get_state<player_::Empty&>().entry_counter == 1,"Empty entry not called correctly");
p.process_event(open_close());
BOOST_CHECK_MESSAGE(p.current_state()[0] == 1,"Open should be active"); //Open
BOOST_CHECK_MESSAGE(p.get_state<player_::Empty&>().exit_counter == 1,"Empty exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::Open&>().entry_counter == 1,"Open entry not called correctly");
p.process_event(open_close());
BOOST_CHECK_MESSAGE(p.current_state()[0] == 2,"Empty should be active"); //Empty
BOOST_CHECK_MESSAGE(p.get_state<player_::Open&>().exit_counter == 1,"Open exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::Empty&>().entry_counter == 2,"Empty entry not called correctly");
BOOST_CHECK_MESSAGE(p.can_close_drawer_counter == 1,"guard not called correctly");
p.process_event(
cd_detected("louie, louie",DISK_DVD));
BOOST_CHECK_MESSAGE(p.current_state()[0] == 2,"Empty should be active"); //Empty
BOOST_CHECK_MESSAGE(p.get_state<player_::Open&>().exit_counter == 1,"Open exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::Empty&>().entry_counter == 2,"Empty entry not called correctly");
p.process_event(
cd_detected("louie, louie",DISK_CD));
BOOST_CHECK_MESSAGE(p.current_state()[0] == 3,"Playing should be active"); //Playing
BOOST_CHECK_MESSAGE(p.get_state<player_::Empty&>().exit_counter == 2,"Empty exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::Stopped&>().entry_counter == 1,"Stopped entry not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::Stopped&>().exit_counter == 1,"Stopped exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::Playing&>().entry_counter == 1,"Playing entry not called correctly");
BOOST_CHECK_MESSAGE(p.start_playback_counter == 1,"action not called correctly");
BOOST_CHECK_MESSAGE(p.test_fct_counter == 1,"action not called correctly");
p.process_event(pause());
BOOST_CHECK_MESSAGE(p.current_state()[0] == 4,"Paused should be active"); //Paused
BOOST_CHECK_MESSAGE(p.get_state<player_::Playing&>().exit_counter == 1,"Playing exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::Paused&>().entry_counter == 1,"Paused entry not called correctly");
// go back to Playing
p.process_event(end_pause());
BOOST_CHECK_MESSAGE(p.current_state()[0] == 3,"Playing should be active"); //Playing
BOOST_CHECK_MESSAGE(p.get_state<player_::Paused&>().exit_counter == 1,"Paused exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::Playing&>().entry_counter == 2,"Playing entry not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::Playing&>().event_counter == 1,"Playing event counter incorrect");
p.process_event(pause());
BOOST_CHECK_MESSAGE(p.current_state()[0] == 4,"Paused should be active"); //Paused
BOOST_CHECK_MESSAGE(p.get_state<player_::Playing&>().exit_counter == 2,"Playing exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::Paused&>().entry_counter == 2,"Paused entry not called correctly");
p.process_event(stop());
BOOST_CHECK_MESSAGE(p.current_state()[0] == 0,"Stopped should be active"); //Stopped
BOOST_CHECK_MESSAGE(p.get_state<player_::Paused&>().exit_counter == 2,"Paused exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::Stopped&>().entry_counter == 2,"Stopped entry not called correctly");
p.process_event(stop());
BOOST_CHECK_MESSAGE(p.current_state()[0] == 0,"Stopped should be active"); //Stopped
BOOST_CHECK_MESSAGE(p.get_state<player_::Stopped&>().exit_counter == 2,"Stopped exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::Stopped&>().entry_counter == 3,"Stopped entry not called correctly");
}
}
-170
View File
@@ -1,170 +0,0 @@
// 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)
// back-end
#include <boost/msm/back11/state_machine.hpp>
//front-end
#include <boost/msm/front/state_machine_def.hpp>
#include <boost/msm/front/functor_row.hpp>
#ifndef BOOST_MSM_NONSTANDALONE_TEST
#define BOOST_TEST_MODULE Back11TestDeferIn2Regions
#endif
#include <boost/test/unit_test.hpp>
namespace msm = boost::msm;
namespace mpl = boost::mpl;
using namespace boost::msm::front;
namespace
{
// events
struct event1 {};
struct event2 {};
struct event3 {};
struct eventd {};
// front-end: define the FSM structure
struct player_ : public msm::front::state_machine_def<player_>
{
// The list of FSM states
struct State11 : public msm::front::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;
int exit_counter;
};
struct State12 : public msm::front::state<>
{
typedef boost::fusion::vector<eventd> deferred_events;
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;
int exit_counter;
};
struct State13 : public msm::front::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;
int exit_counter;
};
struct State21 : public msm::front::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;
int exit_counter;
};
struct State22 : public msm::front::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;
int exit_counter;
};
// the initial state of the player SM. Must be defined
typedef boost::fusion::vector<State11,State21> initial_state;
// Transition table for player
struct transition_table : boost::fusion::vector<
// Start Event Next Action Guard
// +---------+-------------+---------+---------------------+----------------------+
Row < State11 , event1 , State12 >,
Row < State12 , event2 , State13 >,
Row < State21 , event3 , State22 >,
Row < State22 , eventd , State21 >
// +---------+-------------+---------+---------------------+----------------------+
> {};
// Replaces the default no-transition response.
template <class FSM,class Event>
void no_transition(Event const& , FSM&,int )
{
BOOST_FAIL("no_transition called!");
}
// init counters
template <class Event,class FSM>
void on_entry(Event const&,FSM& fsm)
{
fsm.template get_state<player_::State11&>().entry_counter=0;
fsm.template get_state<player_::State11&>().exit_counter=0;
fsm.template get_state<player_::State12&>().entry_counter=0;
fsm.template get_state<player_::State12&>().exit_counter=0;
fsm.template get_state<player_::State13&>().entry_counter=0;
fsm.template get_state<player_::State13&>().exit_counter=0;
fsm.template get_state<player_::State21&>().entry_counter=0;
fsm.template get_state<player_::State22&>().exit_counter=0;
}
};
// Pick a back-end
typedef msm::back11::state_machine<player_> player;
BOOST_AUTO_TEST_CASE( Back11TestDeferIn2Regions )
{
player p;
// needed to start the highest-level SM. This will call on_entry and mark the start of the SM
p.start();
p.process_event(event1());
BOOST_CHECK_MESSAGE(p.current_state()[0] == 1,"State12 should be active");
BOOST_CHECK_MESSAGE(p.current_state()[1] == 2,"State21 should be active");
BOOST_CHECK_MESSAGE(p.get_state<player_::State11&>().exit_counter == 1,"State11 exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::State11&>().entry_counter == 1,"State11 entry not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::State12&>().entry_counter == 1,"State12 entry not called correctly");
// deferred
p.process_event(eventd());
BOOST_CHECK_MESSAGE(p.current_state()[0] == 1,"State12 should be active");
BOOST_CHECK_MESSAGE(p.current_state()[1] == 2,"State21 should be active");
BOOST_CHECK_MESSAGE(p.get_state<player_::State11&>().exit_counter == 1,"State11 exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::State11&>().entry_counter == 1,"State11 entry not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::State12&>().entry_counter == 1,"State12 entry not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::State12&>().exit_counter == 0,"State12 exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::State21&>().exit_counter == 0,"State21 exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::State21&>().entry_counter == 1,"State21 entry not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::State22&>().exit_counter == 0,"State22 exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::State22&>().entry_counter == 0,"State22 entry not called correctly");
p.process_event(event3());
BOOST_CHECK_MESSAGE(p.current_state()[0] == 1,"State12 should be active");
BOOST_CHECK_MESSAGE(p.current_state()[1] == 2,"State21 should be active");
BOOST_CHECK_MESSAGE(p.get_state<player_::State21&>().exit_counter == 1,"State21 exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::State21&>().entry_counter == 2,"State21 entry not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::State22&>().exit_counter == 1,"State22 exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::State22&>().entry_counter == 1,"State22 entry not called correctly");
BOOST_CHECK_MESSAGE(p.get_deferred_queue().size() == 1,"Deferred queue should have one element");
p.clear_deferred_queue();
p.process_event(event2());
BOOST_CHECK_MESSAGE(p.current_state()[0] == 4,"State13 should be active");
BOOST_CHECK_MESSAGE(p.current_state()[1] == 2,"State21 should be active");
BOOST_CHECK_MESSAGE(p.get_state<player_::State21&>().exit_counter == 1,"State21 exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::State21&>().entry_counter == 2,"State21 entry not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::State22&>().exit_counter == 1,"State22 exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::State22&>().entry_counter == 1,"State22 entry not called correctly");
BOOST_CHECK_MESSAGE(p.get_deferred_queue().size() == 0,"Deferred queue should have no element");
}
}
+53
View File
@@ -0,0 +1,53 @@
// Copyright 2024 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)
// back-end
#include <boost/msm/back/state_machine.hpp>
#include <boost/msm/back/favor_compile_time.hpp>
#include <boost/msm/back11/state_machine.hpp>
template<typename Front>
using get_test_machines = boost::mpl::vector<
boost::msm::back::state_machine<Front>,
boost::msm::back::state_machine<Front, boost::msm::back::favor_compile_time>,
boost::msm::back11::state_machine<Front>
>;
#define BOOST_MSM_TEST_DEFINE_DEPENDENT_TEMPLATES(frontname) \
using base = msm::front::state_machine_def<frontname>; \
template<typename T1, class Event, typename T2> \
using _row = typename base::template _row<T1, Event, T2>; \
template< \
typename T1, \
class Event, \
typename T2, \
void (frontname::*action)(Event const&), \
bool (frontname::*guard)(Event const&) \
> using row = typename base::template row<T1, Event, T2, action, guard>; \
template< \
typename T1, \
class Event, \
typename T2, \
void (frontname::*action)(Event const&) \
> using a_row = typename base::template a_row<T1, Event, T2, action>; \
template< \
typename T1, \
class Event, \
typename T2, \
bool (frontname::*guard)(Event const&) \
> using g_row = typename base::template g_row<T1, Event, T2, guard>;
// template<typename State, typename Fsm>
// State& get_state(Fsm&& fsm)
// {
// return fsm.template get_state<State&>();
// }
+29 -24
View File
@@ -8,11 +8,16 @@
// file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#define BOOST_MPL_CFG_NO_PREPROCESSED_HEADERS
#define BOOST_MPL_LIMIT_VECTOR_SIZE 30
// back-end
#include <boost/msm/back/state_machine.hpp>
#include "BackCommon.hpp"
//front-end
#include <boost/msm/front/state_machine_def.hpp>
#ifndef BOOST_MSM_NONSTANDALONE_TEST
#define BOOST_TEST_MODULE big_with_functors_test
#endif
#include <boost/test/unit_test.hpp>
namespace msm = boost::msm;
@@ -195,20 +200,20 @@ namespace
}
};
// Pick a back-end
typedef msm::back::state_machine<my_machine_> my_machine;
typedef get_test_machines<my_machine_> my_machines;
BOOST_AUTO_TEST_CASE( big_with_functors_test )
BOOST_AUTO_TEST_CASE_TEMPLATE( big_with_functors_test, my_machine, my_machines )
{
my_machine p;
// needed to start the highest-level SM.
p.start();
BOOST_CHECK_MESSAGE(p.current_state()[0] == 0,"State1 should be active"); //State1
BOOST_CHECK_MESSAGE(p.get_state<my_machine_::State1&>().exit_counter == 0,"State1 exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<my_machine_::State1&>().entry_counter == 1,"State1 entry not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<my_machine_::State5&>().exit_counter == 0,"State5 exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<my_machine_::State5&>().entry_counter == 0,"State5 entry not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<my_machine_::State1&>().exit_counter == 0,"State1 exit not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<my_machine_::State1&>().entry_counter == 1,"State1 entry not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<my_machine_::State5&>().exit_counter == 0,"State5 exit not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<my_machine_::State5&>().entry_counter == 0,"State5 entry not called correctly");
p.process_event(event1());
p.process_event(event1());
@@ -223,14 +228,14 @@ namespace
p.process_event(event1());
BOOST_CHECK_MESSAGE(p.current_state()[0] == 11,"State12 should be active"); //State12
BOOST_CHECK_MESSAGE(p.get_state<my_machine_::State12&>().exit_counter == 0,"State12 exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<my_machine_::State12&>().entry_counter == 1,"State12 entry not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<my_machine_::State2&>().exit_counter == 1,"State2 exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<my_machine_::State2&>().entry_counter == 1,"State2 entry not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<my_machine_::State7&>().exit_counter == 1,"State7 exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<my_machine_::State7&>().entry_counter == 1,"State7 entry not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<my_machine_::State10&>().exit_counter == 1,"State10 exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<my_machine_::State10&>().entry_counter == 1,"State10 entry not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<my_machine_::State12&>().exit_counter == 0,"State12 exit not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<my_machine_::State12&>().entry_counter == 1,"State12 entry not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<my_machine_::State2&>().exit_counter == 1,"State2 exit not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<my_machine_::State2&>().entry_counter == 1,"State2 entry not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<my_machine_::State7&>().exit_counter == 1,"State7 exit not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<my_machine_::State7&>().entry_counter == 1,"State7 entry not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<my_machine_::State10&>().exit_counter == 1,"State10 exit not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<my_machine_::State10&>().entry_counter == 1,"State10 entry not called correctly");
p.process_event(event2());
@@ -246,14 +251,14 @@ namespace
p.process_event(event2());
BOOST_CHECK_MESSAGE(p.current_state()[0] == 0,"State1 should be active"); //State1
BOOST_CHECK_MESSAGE(p.get_state<my_machine_::State1&>().exit_counter == 1,"State1 exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<my_machine_::State1&>().entry_counter == 2,"State1 entry not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<my_machine_::State2&>().exit_counter == 2,"State2 exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<my_machine_::State2&>().entry_counter == 2,"State2 entry not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<my_machine_::State7&>().exit_counter == 2,"State7 exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<my_machine_::State7&>().entry_counter == 2,"State7 entry not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<my_machine_::State10&>().exit_counter == 2,"State10 exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<my_machine_::State10&>().entry_counter == 2,"State10 entry not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<my_machine_::State1&>().exit_counter == 1,"State1 exit not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<my_machine_::State1&>().entry_counter == 2,"State1 entry not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<my_machine_::State2&>().exit_counter == 2,"State2 exit not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<my_machine_::State2&>().entry_counter == 2,"State2 entry not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<my_machine_::State7&>().exit_counter == 2,"State7 exit not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<my_machine_::State7&>().entry_counter == 2,"State7 entry not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<my_machine_::State10&>().exit_counter == 2,"State10 exit not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<my_machine_::State10&>().entry_counter == 2,"State10 entry not called correctly");
}
}
+18
View File
@@ -0,0 +1,18 @@
file(GLOB SOURCES "*.cpp")
# TODO:
# Fully install boost to test Serialize
list(FILTER SOURCES EXCLUDE REGEX "Serialize|BigWithFunctors")
# list(FILTER SOURCES INCLUDE REGEX "Anonymous")
add_executable(msm_test
${SOURCES}
# Anonymous.cpp
# AnonymousEuml.cpp
# AnonymousAndGuard.cpp
# BigWithFunctors.cpp
# CompositeMachine.cpp
# Entries.cpp
main.cpp
)
target_include_directories(msm_test PRIVATE ../include)
target_compile_definitions(msm_test PRIVATE "BOOST_MSM_NONSTANDALONE_TEST")
+64 -46
View File
@@ -8,11 +8,11 @@
// file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#include <boost/msm/back/state_machine.hpp>
#include "BackCommon.hpp"
#include <boost/msm/front/euml/euml.hpp>
#ifndef BOOST_MSM_NONSTANDALONE_TEST
#define BOOST_TEST_MODULE MyTest
#define BOOST_TEST_MODULE composite_euml_test
#endif
#include <boost/test/unit_test.hpp>
@@ -52,9 +52,14 @@ namespace
BOOST_MSM_EUML_STATE(( ++state_(entry_counter),++state_(exit_counter),attributes_ << entry_counter << exit_counter),Stopped)
BOOST_MSM_EUML_STATE(( ++state_(entry_counter),++state_(exit_counter),attributes_ << entry_counter << exit_counter),Paused)
// Playing is now a state machine itself.
// State machine attributes.
BOOST_MSM_EUML_DECLARE_ATTRIBUTE(unsigned int,start_next_song_counter)
BOOST_MSM_EUML_DECLARE_ATTRIBUTE(unsigned int,start_prev_song_guard_counter)
BOOST_MSM_EUML_DECLARE_ATTRIBUTE(unsigned int,start_playback_counter)
BOOST_MSM_EUML_DECLARE_ATTRIBUTE(unsigned int,can_close_drawer_counter)
BOOST_MSM_EUML_DECLARE_ATTRIBUTE(unsigned int,test_fct_counter)
// Playing is now a state machine itself.
// It has 5 substates
BOOST_MSM_EUML_STATE(( ++state_(entry_counter),++state_(exit_counter),attributes_ << entry_counter << exit_counter),Song1)
BOOST_MSM_EUML_STATE(( ++state_(entry_counter),++state_(exit_counter),attributes_ << entry_counter << exit_counter),Song2)
@@ -62,6 +67,9 @@ namespace
BOOST_MSM_EUML_STATE(( ++state_(entry_counter),++state_(exit_counter),attributes_ << entry_counter << exit_counter),Region2State1)
BOOST_MSM_EUML_STATE(( ++state_(entry_counter),++state_(exit_counter),attributes_ << entry_counter << exit_counter),Region2State2)
template<template <typename...> class Back, typename Policy = void>
struct hierarchical_state_machine
{
// Playing has a transition table
BOOST_MSM_EUML_TRANSITION_TABLE((
// +------------------------------------------------------------------------------+
@@ -82,14 +90,11 @@ namespace
<< start_prev_song_guard_counter // Attributes
),Playing_)
// choice of back-end
typedef msm::back::state_machine<Playing_> Playing_type;
typedef Back<Playing_, Policy> Playing_type;
Playing_type const Playing;
//fsm
BOOST_MSM_EUML_DECLARE_ATTRIBUTE(unsigned int,start_playback_counter)
BOOST_MSM_EUML_DECLARE_ATTRIBUTE(unsigned int,can_close_drawer_counter)
BOOST_MSM_EUML_DECLARE_ATTRIBUTE(unsigned int,test_fct_counter)
BOOST_MSM_EUML_ACTION(No_Transition)
{
template <class FSM,class Event>
@@ -142,138 +147,151 @@ namespace
),
player_) //fsm name
typedef msm::back::state_machine<player_> player;
typedef Back<player_, Policy> player;
};
typedef boost::mpl::vector<
hierarchical_state_machine<boost::msm::back::state_machine>,
hierarchical_state_machine<boost::msm::back::state_machine, boost::msm::back::favor_compile_time>,
hierarchical_state_machine<boost::msm::back11::state_machine>
> test_machines;
// static char const* const state_names[] = { "Stopped", "Paused", "Open", "Empty", "Playing" };
BOOST_AUTO_TEST_CASE( my_test )
BOOST_AUTO_TEST_CASE_TEMPLATE( composite_euml_test, test_machine, test_machines )
{
player p;
typename test_machine::player p;
typedef typename test_machine::player_ player_;
typedef typename test_machine::Playing_type Playing_type;
p.start();
BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(Empty)&>().get_attribute(entry_counter) == 1,
BOOST_CHECK_MESSAGE(p.template get_state<BOOST_MSM_EUML_STATE_NAME(Empty)&>().get_attribute(entry_counter) == 1,
"Empty entry not called correctly");
p.process_event(open_close());
BOOST_CHECK_MESSAGE(p.current_state()[0] == 2,"Open should be active"); //Open
BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(Empty)&>().get_attribute(exit_counter) == 1,
BOOST_CHECK_MESSAGE(p.template get_state<BOOST_MSM_EUML_STATE_NAME(Empty)&>().get_attribute(exit_counter) == 1,
"Empty exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(Open)&>().get_attribute(entry_counter) == 1,
BOOST_CHECK_MESSAGE(p.template get_state<BOOST_MSM_EUML_STATE_NAME(Open)&>().get_attribute(entry_counter) == 1,
"Open entry not called correctly");
p.process_event(open_close());
BOOST_CHECK_MESSAGE(p.current_state()[0] == 3,"Empty should be active"); //Empty
BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(Open)&>().get_attribute(exit_counter) == 1,
BOOST_CHECK_MESSAGE(p.template get_state<BOOST_MSM_EUML_STATE_NAME(Open)&>().get_attribute(exit_counter) == 1,
"Open exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(Empty)&>().get_attribute(entry_counter) == 2,
BOOST_CHECK_MESSAGE(p.template get_state<BOOST_MSM_EUML_STATE_NAME(Empty)&>().get_attribute(entry_counter) == 2,
"Empty entry not called correctly");
BOOST_CHECK_MESSAGE(p.get_attribute(can_close_drawer_counter) == 1,"guard not called correctly");
p.process_event(
cd_detected("louie, louie",DISK_DVD));
BOOST_CHECK_MESSAGE(p.current_state()[0] == 3,"Empty should be active"); //Empty
BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(Open)&>().get_attribute(exit_counter) == 1,
BOOST_CHECK_MESSAGE(p.template get_state<BOOST_MSM_EUML_STATE_NAME(Open)&>().get_attribute(exit_counter) == 1,
"Open exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(Empty)&>().get_attribute(entry_counter) == 2,
BOOST_CHECK_MESSAGE(p.template get_state<BOOST_MSM_EUML_STATE_NAME(Empty)&>().get_attribute(entry_counter) == 2,
"Empty entry not called correctly");
p.process_event(
cd_detected("louie, louie",DISK_CD));
BOOST_CHECK_MESSAGE(p.current_state()[0] == 4,"Playing should be active"); //Playing
BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(Empty)&>().get_attribute(exit_counter) == 2,
BOOST_CHECK_MESSAGE(p.template get_state<BOOST_MSM_EUML_STATE_NAME(Empty)&>().get_attribute(exit_counter) == 2,
"Empty exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(Stopped)&>().get_attribute(entry_counter) == 1,
BOOST_CHECK_MESSAGE(p.template get_state<BOOST_MSM_EUML_STATE_NAME(Stopped)&>().get_attribute(entry_counter) == 1,
"Stopped entry not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(Stopped)&>().get_attribute(exit_counter) == 1,
BOOST_CHECK_MESSAGE(p.template get_state<BOOST_MSM_EUML_STATE_NAME(Stopped)&>().get_attribute(exit_counter) == 1,
"Stopped exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<Playing_type&>().get_attribute(entry_counter) == 1,
BOOST_CHECK_MESSAGE(p.template get_state<Playing_type&>().get_attribute(entry_counter) == 1,
"Playing entry not called correctly");
BOOST_CHECK_MESSAGE(p.get_attribute(start_playback_counter) == 1,"action not called correctly");
BOOST_CHECK_MESSAGE(p.get_attribute(test_fct_counter) == 1,"action not called correctly");
p.process_event(next_song);
BOOST_CHECK_MESSAGE(p.current_state()[0] == 4,"Playing should be active"); //Playing
BOOST_CHECK_MESSAGE(p.get_state<Playing_type&>().current_state()[0] == 1,"Song2 should be active");
BOOST_CHECK_MESSAGE(p.get_state<Playing_type&>().current_state()[1] == 3,"Region2State1 should be active");
BOOST_CHECK_MESSAGE(p.template get_state<Playing_type&>().current_state()[0] == 1,"Song2 should be active");
BOOST_CHECK_MESSAGE(p.template get_state<Playing_type&>().current_state()[1] == 3,"Region2State1 should be active");
BOOST_CHECK_MESSAGE(
p.get_state<Playing_type&>().get_state<BOOST_MSM_EUML_STATE_NAME(Region2State1)&>().get_attribute(entry_counter) == 1,
p.template get_state<Playing_type&>().template get_state<BOOST_MSM_EUML_STATE_NAME(Region2State1)&>().get_attribute(entry_counter) == 1,
"Region2State1 entry not called correctly");
BOOST_CHECK_MESSAGE(
p.get_state<Playing_type&>().get_state<BOOST_MSM_EUML_STATE_NAME(Song2)&>().get_attribute(entry_counter) == 1,
p.template get_state<Playing_type&>().template get_state<BOOST_MSM_EUML_STATE_NAME(Song2)&>().get_attribute(entry_counter) == 1,
"Song2 entry not called correctly");
BOOST_CHECK_MESSAGE(
p.get_state<Playing_type&>().get_state<BOOST_MSM_EUML_STATE_NAME(Song1)&>().get_attribute(exit_counter) == 1,
p.template get_state<Playing_type&>().template get_state<BOOST_MSM_EUML_STATE_NAME(Song1)&>().get_attribute(exit_counter) == 1,
"Song1 exit not called correctly");
BOOST_CHECK_MESSAGE(
p.get_state<Playing_type&>().get_attribute(start_next_song_counter) == 0,
p.template get_state<Playing_type&>().get_attribute(start_next_song_counter) == 0,
"submachine action not called correctly");
p.process_event(next_song);
BOOST_CHECK_MESSAGE(p.current_state()[0] == 4,"Playing should be active"); //Playing
BOOST_CHECK_MESSAGE(p.get_state<Playing_type&>().current_state()[0] == 2,"Song3 should be active");
BOOST_CHECK_MESSAGE(p.template get_state<Playing_type&>().current_state()[0] == 2,"Song3 should be active");
BOOST_CHECK_MESSAGE(
p.get_state<Playing_type&>().get_state<BOOST_MSM_EUML_STATE_NAME(Song3)&>().get_attribute(entry_counter) == 1,
p.template get_state<Playing_type&>().template get_state<BOOST_MSM_EUML_STATE_NAME(Song3)&>().get_attribute(entry_counter) == 1,
"Song3 entry not called correctly");
BOOST_CHECK_MESSAGE(
p.get_state<Playing_type&>().get_state<BOOST_MSM_EUML_STATE_NAME(Song2)&>().get_attribute(exit_counter) == 1,
p.template get_state<Playing_type&>().template get_state<BOOST_MSM_EUML_STATE_NAME(Song2)&>().get_attribute(exit_counter) == 1,
"Song2 exit not called correctly");
BOOST_CHECK_MESSAGE(
p.get_state<Playing_type&>().get_attribute(start_next_song_counter) == 1,
p.template get_state<Playing_type&>().get_attribute(start_next_song_counter) == 1,
"submachine action not called correctly");
p.process_event(previous_song);
BOOST_CHECK_MESSAGE(p.current_state()[0] == 4,"Playing should be active"); //Playing
BOOST_CHECK_MESSAGE(p.get_state<Playing_type&>().current_state()[0] == 1,"Song2 should be active");
BOOST_CHECK_MESSAGE(p.template get_state<Playing_type&>().current_state()[0] == 1,"Song2 should be active");
BOOST_CHECK_MESSAGE(
p.get_state<Playing_type&>().get_state<BOOST_MSM_EUML_STATE_NAME(Song2)&>().get_attribute(entry_counter) == 2,
p.template get_state<Playing_type&>().template get_state<BOOST_MSM_EUML_STATE_NAME(Song2)&>().get_attribute(entry_counter) == 2,
"Song2 entry not called correctly");
BOOST_CHECK_MESSAGE(
p.get_state<Playing_type&>().get_state<BOOST_MSM_EUML_STATE_NAME(Song3)&>().get_attribute(exit_counter) == 1,
p.template get_state<Playing_type&>().template get_state<BOOST_MSM_EUML_STATE_NAME(Song3)&>().get_attribute(exit_counter) == 1,
"Song3 exit not called correctly");
BOOST_CHECK_MESSAGE(
p.get_state<Playing_type&>().get_attribute(start_prev_song_guard_counter) == 1,
p.template get_state<Playing_type&>().get_attribute(start_prev_song_guard_counter) == 1,
"submachine guard not called correctly");
BOOST_CHECK_MESSAGE(
p.get_state<Playing_type&>().get_state<BOOST_MSM_EUML_STATE_NAME(Region2State2)&>().get_attribute(entry_counter) == 0,
p.template get_state<Playing_type&>().template get_state<BOOST_MSM_EUML_STATE_NAME(Region2State2)&>().get_attribute(entry_counter) == 0,
"Region2State2 entry not called correctly");
p.process_event(pause());
BOOST_CHECK_MESSAGE(p.current_state()[0] == 1,"Paused should be active"); //Paused
BOOST_CHECK_MESSAGE(p.get_state<Playing_type&>().get_attribute(exit_counter) == 1,
BOOST_CHECK_MESSAGE(p.template get_state<Playing_type&>().get_attribute(exit_counter) == 1,
"Playing exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(Paused)&>().get_attribute(entry_counter) == 1,
BOOST_CHECK_MESSAGE(p.template get_state<BOOST_MSM_EUML_STATE_NAME(Paused)&>().get_attribute(entry_counter) == 1,
"Paused entry not called correctly");
// go back to Playing
p.process_event(end_pause());
BOOST_CHECK_MESSAGE(p.current_state()[0] == 4,"Playing should be active"); //Playing
BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(Paused)&>().get_attribute(exit_counter) == 1,
BOOST_CHECK_MESSAGE(p.template get_state<BOOST_MSM_EUML_STATE_NAME(Paused)&>().get_attribute(exit_counter) == 1,
"Paused exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<Playing_type&>().get_attribute(entry_counter) == 2,
BOOST_CHECK_MESSAGE(p.template get_state<Playing_type&>().get_attribute(entry_counter) == 2,
"Playing entry not called correctly");
p.process_event(pause());
BOOST_CHECK_MESSAGE(p.current_state()[0] == 1,"Paused should be active"); //Paused
BOOST_CHECK_MESSAGE(p.get_state<Playing_type&>().get_attribute(exit_counter) == 2,
BOOST_CHECK_MESSAGE(p.template get_state<Playing_type&>().get_attribute(exit_counter) == 2,
"Playing exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(Paused)&>().get_attribute(entry_counter) == 2,
BOOST_CHECK_MESSAGE(p.template get_state<BOOST_MSM_EUML_STATE_NAME(Paused)&>().get_attribute(entry_counter) == 2,
"Paused entry not called correctly");
p.process_event(stop());
BOOST_CHECK_MESSAGE(p.current_state()[0] == 0,"Stopped should be active"); //Stopped
BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(Paused)&>().get_attribute(exit_counter) == 2,
BOOST_CHECK_MESSAGE(p.template get_state<BOOST_MSM_EUML_STATE_NAME(Paused)&>().get_attribute(exit_counter) == 2,
"Paused exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(Stopped)&>().get_attribute(entry_counter) == 2,
BOOST_CHECK_MESSAGE(p.template get_state<BOOST_MSM_EUML_STATE_NAME(Stopped)&>().get_attribute(entry_counter) == 2,
"Stopped entry not called correctly");
p.process_event(stop());
BOOST_CHECK_MESSAGE(p.current_state()[0] == 0,"Stopped should be active"); //Stopped
BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(Stopped)&>().get_attribute(exit_counter) == 2,
BOOST_CHECK_MESSAGE(p.template get_state<BOOST_MSM_EUML_STATE_NAME(Stopped)&>().get_attribute(exit_counter) == 2,
"Stopped exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(Stopped)&>().get_attribute(entry_counter) == 3,
BOOST_CHECK_MESSAGE(p.template get_state<BOOST_MSM_EUML_STATE_NAME(Stopped)&>().get_attribute(entry_counter) == 3,
"Stopped entry not called correctly");
}
}
using back0 = hierarchical_state_machine<boost::msm::back::state_machine, boost::msm::back::favor_compile_time>::player;
using back1 = hierarchical_state_machine<boost::msm::back::state_machine, boost::msm::back::favor_compile_time>::Playing_type;
BOOST_MSM_BACK_GENERATE_PROCESS_EVENT(back0);
BOOST_MSM_BACK_GENERATE_PROCESS_EVENT(back1);
+72 -55
View File
@@ -9,11 +9,11 @@
// http://www.boost.org/LICENSE_1_0.txt)
// back-end
#include <boost/msm/back/state_machine.hpp>
#include "BackCommon.hpp"
//front-end
#include <boost/msm/front/state_machine_def.hpp>
#ifndef BOOST_MSM_NONSTANDALONE_TEST
#define BOOST_TEST_MODULE MyTest
#define BOOST_TEST_MODULE composite_machine_test
#endif
#include <boost/test/unit_test.hpp>
@@ -38,9 +38,14 @@ namespace
std::string name;
};
template<template <typename...> class Back, typename Policy = void>
struct hierarchical_state_machine
{
// front-end: define the FSM structure
struct player_ : public msm::front::state_machine_def<player_>
{
BOOST_MSM_TEST_DEFINE_DEPENDENT_TEMPLATES(player_);
unsigned int start_playback_counter;
unsigned int can_close_drawer_counter;
@@ -81,6 +86,8 @@ namespace
struct Playing_ : public msm::front::state_machine_def<Playing_>
{
BOOST_MSM_TEST_DEFINE_DEPENDENT_TEMPLATES(Playing_);
template <class Event,class FSM>
void on_entry(Event const&,FSM& ) {++entry_counter;}
template <class Event,class FSM>
@@ -150,7 +157,7 @@ namespace
}
};
// back-end
typedef msm::back::state_machine<Playing_> Playing;
typedef Back<Playing_, Policy> Playing;
// state not defining any entry or exit
struct Paused : public msm::front::state<>
@@ -217,128 +224,138 @@ namespace
template <class Event,class FSM>
void on_entry(Event const&,FSM& fsm)
{
fsm.template get_state<player_::Stopped&>().entry_counter=0;
fsm.template get_state<player_::Stopped&>().exit_counter=0;
fsm.template get_state<player_::Open&>().entry_counter=0;
fsm.template get_state<player_::Open&>().exit_counter=0;
fsm.template get_state<player_::Empty&>().entry_counter=0;
fsm.template get_state<player_::Empty&>().exit_counter=0;
fsm.template get_state<player_::Playing&>().entry_counter=0;
fsm.template get_state<player_::Playing&>().exit_counter=0;
fsm.template get_state<player_::Playing&>().template get_state<player_::Playing::Song1&>().entry_counter=0;
fsm.template get_state<player_::Playing&>().template get_state<player_::Playing::Song1&>().exit_counter=0;
fsm.template get_state<player_::Playing&>().template get_state<player_::Playing::Song2&>().entry_counter=0;
fsm.template get_state<player_::Playing&>().template get_state<player_::Playing::Song2&>().exit_counter=0;
fsm.template get_state<player_::Playing&>().template get_state<player_::Playing::Song3&>().entry_counter=0;
fsm.template get_state<player_::Playing&>().template get_state<player_::Playing::Song3&>().exit_counter=0;
fsm.template get_state<player_::Paused&>().entry_counter=0;
fsm.template get_state<player_::Paused&>().exit_counter=0;
fsm.template get_state<typename player_::Stopped&>().entry_counter=0;
fsm.template get_state<typename player_::Stopped&>().exit_counter=0;
fsm.template get_state<typename player_::Open&>().entry_counter=0;
fsm.template get_state<typename player_::Open&>().exit_counter=0;
fsm.template get_state<typename player_::Empty&>().entry_counter=0;
fsm.template get_state<typename player_::Empty&>().exit_counter=0;
fsm.template get_state<typename player_::Playing&>().entry_counter=0;
fsm.template get_state<typename player_::Playing&>().exit_counter=0;
fsm.template get_state<typename player_::Playing&>().template get_state<typename player_::Playing::Song1&>().exit_counter=0;
fsm.template get_state<typename player_::Playing&>().template get_state<typename player_::Playing::Song2&>().entry_counter=0;
fsm.template get_state<typename player_::Playing&>().template get_state<typename player_::Playing::Song2&>().exit_counter=0;
fsm.template get_state<typename player_::Playing&>().template get_state<typename player_::Playing::Song3&>().entry_counter=0;
fsm.template get_state<typename player_::Playing&>().template get_state<typename player_::Playing::Song3&>().exit_counter=0;
fsm.template get_state<typename player_::Paused&>().entry_counter=0;
fsm.template get_state<typename player_::Paused&>().exit_counter=0;
}
};
typedef Back<player_, Policy> player;
};
// Pick a back-end
typedef msm::back::state_machine<player_> player;
typedef boost::mpl::vector<
hierarchical_state_machine<boost::msm::back::state_machine>,
hierarchical_state_machine<boost::msm::back::state_machine, boost::msm::back::favor_compile_time>,
hierarchical_state_machine<boost::msm::back11::state_machine>
> test_machines;
// static char const* const state_names[] = { "Stopped", "Open", "Empty", "Playing", "Paused" };
BOOST_AUTO_TEST_CASE( composite_machine_test )
BOOST_AUTO_TEST_CASE_TEMPLATE( composite_machine_test, test_machine, test_machines )
{
player p;
typename test_machine::player p;
typedef typename test_machine::player_ player_;
p.start();
BOOST_CHECK_MESSAGE(p.get_state<player_::Empty&>().entry_counter == 1,"Empty entry not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<typename player_::Empty&>().entry_counter == 1,"Empty entry not called correctly");
p.process_event(open_close());
BOOST_CHECK_MESSAGE(p.current_state()[0] == 1,"Open should be active"); //Open
BOOST_CHECK_MESSAGE(p.get_state<player_::Empty&>().exit_counter == 1,"Empty exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::Open&>().entry_counter == 1,"Open entry not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<typename player_::Empty&>().exit_counter == 1,"Empty exit not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<typename player_::Open&>().entry_counter == 1,"Open entry not called correctly");
p.process_event(open_close());
BOOST_CHECK_MESSAGE(p.current_state()[0] == 2,"Empty should be active"); //Empty
BOOST_CHECK_MESSAGE(p.get_state<player_::Open&>().exit_counter == 1,"Open exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::Empty&>().entry_counter == 2,"Empty entry not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<typename player_::Open&>().exit_counter == 1,"Open exit not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<typename player_::Empty&>().entry_counter == 2,"Empty entry not called correctly");
BOOST_CHECK_MESSAGE(p.can_close_drawer_counter == 1,"guard not called correctly");
p.process_event(cd_detected("louie, louie"));
BOOST_CHECK_MESSAGE(p.current_state()[0] == 0,"Stopped should be active"); //Stopped
BOOST_CHECK_MESSAGE(p.get_state<player_::Empty&>().exit_counter == 2,"Empty exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::Stopped&>().entry_counter == 1,"Stopped entry not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<typename player_::Empty&>().exit_counter == 2,"Empty exit not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<typename player_::Stopped&>().entry_counter == 1,"Stopped entry not called correctly");
p.process_event(play());
BOOST_CHECK_MESSAGE(p.current_state()[0] == 3,"Playing should be active"); //Playing
BOOST_CHECK_MESSAGE(p.get_state<player_::Stopped&>().exit_counter == 1,"Stopped exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::Playing&>().entry_counter == 1,"Playing entry not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<typename player_::Stopped&>().exit_counter == 1,"Stopped exit not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<typename player_::Playing&>().entry_counter == 1,"Playing entry not called correctly");
BOOST_CHECK_MESSAGE(p.start_playback_counter == 1,"action not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::Playing&>().current_state()[0] == 0,"Song1 should be active");
BOOST_CHECK_MESSAGE(p.template get_state<typename player_::Playing&>().current_state()[0] == 0,"Song1 should be active");
BOOST_CHECK_MESSAGE(
p.get_state<player_::Playing&>().get_state<player_::Playing::Song1&>().entry_counter == 1,
p.template get_state<typename player_::Playing&>().template get_state<typename player_::Playing::Song1&>().entry_counter == 1,
"Song1 entry not called correctly");
p.process_event(NextSong());
BOOST_CHECK_MESSAGE(p.current_state()[0] == 3,"Playing should be active"); //Playing
BOOST_CHECK_MESSAGE(p.get_state<player_::Playing&>().current_state()[0] == 1,"Song2 should be active");
BOOST_CHECK_MESSAGE(p.template get_state<typename player_::Playing&>().current_state()[0] == 1,"Song2 should be active");
BOOST_CHECK_MESSAGE(
p.get_state<player_::Playing&>().get_state<player_::Playing::Song2&>().entry_counter == 1,
p.template get_state<typename player_::Playing&>().template get_state<typename player_::Playing::Song2&>().entry_counter == 1,
"Song2 entry not called correctly");
BOOST_CHECK_MESSAGE(
p.get_state<player_::Playing&>().get_state<player_::Playing::Song1&>().exit_counter == 1,
p.template get_state<typename player_::Playing&>().template get_state<typename player_::Playing::Song1&>().exit_counter == 1,
"Song1 exit not called correctly");
BOOST_CHECK_MESSAGE(
p.get_state<player_::Playing&>().start_next_song_counter == 0,
p.template get_state<typename player_::Playing&>().start_next_song_counter == 0,
"submachine action not called correctly");
p.process_event(NextSong());
BOOST_CHECK_MESSAGE(p.current_state()[0] == 3,"Playing should be active"); //Playing
BOOST_CHECK_MESSAGE(p.get_state<player_::Playing&>().current_state()[0] == 2,"Song3 should be active");
BOOST_CHECK_MESSAGE(p.template get_state<typename player_::Playing&>().current_state()[0] == 2,"Song3 should be active");
BOOST_CHECK_MESSAGE(
p.get_state<player_::Playing&>().get_state<player_::Playing::Song3&>().entry_counter == 1,
p.template get_state<typename player_::Playing&>().template get_state<typename player_::Playing::Song3&>().entry_counter == 1,
"Song3 entry not called correctly");
BOOST_CHECK_MESSAGE(
p.get_state<player_::Playing&>().get_state<player_::Playing::Song2&>().exit_counter == 1,
p.template get_state<typename player_::Playing&>().template get_state<typename player_::Playing::Song2&>().exit_counter == 1,
"Song2 exit not called correctly");
BOOST_CHECK_MESSAGE(
p.get_state<player_::Playing&>().start_next_song_counter == 1,
p.template get_state<typename player_::Playing&>().start_next_song_counter == 1,
"submachine action not called correctly");
p.process_event(PreviousSong());
BOOST_CHECK_MESSAGE(p.current_state()[0] == 3,"Playing should be active"); //Playing
BOOST_CHECK_MESSAGE(p.get_state<player_::Playing&>().current_state()[0] == 1,"Song2 should be active");
BOOST_CHECK_MESSAGE(p.template get_state<typename player_::Playing&>().current_state()[0] == 1,"Song2 should be active");
BOOST_CHECK_MESSAGE(
p.get_state<player_::Playing&>().get_state<player_::Playing::Song2&>().entry_counter == 2,
p.template get_state<typename player_::Playing&>().template get_state<typename player_::Playing::Song2&>().entry_counter == 2,
"Song2 entry not called correctly");
BOOST_CHECK_MESSAGE(
p.get_state<player_::Playing&>().get_state<player_::Playing::Song3&>().exit_counter == 1,
p.template get_state<typename player_::Playing&>().template get_state<typename player_::Playing::Song3&>().exit_counter == 1,
"Song3 exit not called correctly");
BOOST_CHECK_MESSAGE(
p.get_state<player_::Playing&>().start_prev_song_guard_counter == 1,
p.template get_state<typename player_::Playing&>().start_prev_song_guard_counter == 1,
"submachine guard not called correctly");
p.process_event(pause());
BOOST_CHECK_MESSAGE(p.current_state()[0] == 4,"Paused should be active"); //Paused
BOOST_CHECK_MESSAGE(p.get_state<player_::Playing&>().exit_counter == 1,"Playing exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::Paused&>().entry_counter == 1,"Paused entry not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<typename player_::Playing&>().exit_counter == 1,"Playing exit not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<typename player_::Paused&>().entry_counter == 1,"Paused entry not called correctly");
// go back to Playing
p.process_event(end_pause());
BOOST_CHECK_MESSAGE(p.current_state()[0] == 3,"Playing should be active"); //Playing
BOOST_CHECK_MESSAGE(p.get_state<player_::Paused&>().exit_counter == 1,"Paused exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::Playing&>().entry_counter == 2,"Playing entry not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<typename player_::Paused&>().exit_counter == 1,"Paused exit not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<typename player_::Playing&>().entry_counter == 2,"Playing entry not called correctly");
p.process_event(pause());
BOOST_CHECK_MESSAGE(p.current_state()[0] == 4,"Paused should be active"); //Paused
BOOST_CHECK_MESSAGE(p.get_state<player_::Playing&>().exit_counter == 2,"Playing exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::Paused&>().entry_counter == 2,"Paused entry not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<typename player_::Playing&>().exit_counter == 2,"Playing exit not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<typename player_::Paused&>().entry_counter == 2,"Paused entry not called correctly");
p.process_event(stop());
BOOST_CHECK_MESSAGE(p.current_state()[0] == 0,"Stopped should be active"); //Stopped
BOOST_CHECK_MESSAGE(p.get_state<player_::Paused&>().exit_counter == 2,"Paused exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::Stopped&>().entry_counter == 2,"Stopped entry not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<typename player_::Paused&>().exit_counter == 2,"Paused exit not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<typename player_::Stopped&>().entry_counter == 2,"Stopped entry not called correctly");
p.process_event(stop());
BOOST_CHECK_MESSAGE(p.current_state()[0] == 0,"Stopped should be active"); //Stopped
BOOST_CHECK_MESSAGE(p.get_state<player_::Stopped&>().exit_counter == 2,"Stopped exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::Stopped&>().entry_counter == 3,"Stopped entry not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<typename player_::Stopped&>().exit_counter == 2,"Stopped exit not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<typename player_::Stopped&>().entry_counter == 3,"Stopped entry not called correctly");
}
}
using back0 = hierarchical_state_machine<boost::msm::back::state_machine, boost::msm::back::favor_compile_time>::player;
using back1 = hierarchical_state_machine<boost::msm::back::state_machine, boost::msm::back::favor_compile_time>::player_::Playing;
BOOST_MSM_BACK_GENERATE_PROCESS_EVENT(back0);
BOOST_MSM_BACK_GENERATE_PROCESS_EVENT(back1);
+4 -4
View File
@@ -9,11 +9,11 @@
// http://www.boost.org/LICENSE_1_0.txt)
// back-end
#include <boost/msm/back/state_machine.hpp>
#include "BackCommon.hpp"
//front-end
#include <boost/msm/front/state_machine_def.hpp>
#ifndef BOOST_MSM_NONSTANDALONE_TEST
#define BOOST_TEST_MODULE MyTest
#define BOOST_TEST_MODULE constructor_test
#endif
#include <boost/test/unit_test.hpp>
@@ -189,12 +189,12 @@ namespace
};
// Pick a back-end
typedef msm::back::state_machine<player_> player;
typedef get_test_machines<player_> players;
// static char const* const state_names[] = { "Stopped", "Open", "Empty", "Playing", "Paused" };
BOOST_AUTO_TEST_CASE( my_test )
BOOST_AUTO_TEST_CASE_TEMPLATE( constructor_test, player, players )
{
SomeExternalContext ctx(3);
player p(boost::ref(ctx),5);
+83 -66
View File
@@ -9,11 +9,11 @@
// http://www.boost.org/LICENSE_1_0.txt)
// back-end
#include <boost/msm/back/state_machine.hpp>
#include "BackCommon.hpp"
//front-end
#include <boost/msm/front/state_machine_def.hpp>
#ifndef BOOST_MSM_NONSTANDALONE_TEST
#define BOOST_TEST_MODULE MyTest
#define BOOST_TEST_MODULE entries_test
#endif
#include <boost/test/unit_test.hpp>
@@ -34,9 +34,14 @@ namespace
template <class Event>
event6(Event const&){}
};
template<template <typename...> class Back, typename Policy = void>
struct hierarchical_state_machine
{
// front-end: define the FSM structure
struct Fsm_ : public msm::front::state_machine_def<Fsm_>
{
BOOST_MSM_TEST_DEFINE_DEPENDENT_TEMPLATES(Fsm_);
// The list of FSM states
struct State1 : public msm::front::state<>
{
@@ -58,7 +63,8 @@ namespace
};
struct SubFsm2_ : public msm::front::state_machine_def<SubFsm2_>
{
typedef msm::back::state_machine<SubFsm2_> SubFsm2;
BOOST_MSM_TEST_DEFINE_DEPENDENT_TEMPLATES(SubFsm2_);
typedef Back<SubFsm2_, Policy> SubFsm2;
unsigned int entry_action_counter;
@@ -159,7 +165,7 @@ namespace
BOOST_FAIL("no_transition called!");
}
};
typedef msm::back::state_machine<SubFsm2_> SubFsm2;
typedef Back<SubFsm2_, Policy> SubFsm2;
// the initial state of the player SM. Must be defined
typedef State1 initial_state;
@@ -169,19 +175,19 @@ namespace
// Transition table for Fsm
struct transition_table : mpl::vector<
// Start Event Next Action Guard
// +---------------------+--------+------------------------------------+-------+--------+
_row < State1 , event1 , SubFsm2 >,
_row < State1 , event2 , SubFsm2::direct<SubFsm2_::SubState2> >,
_row < State1 , event3 , mpl::vector<SubFsm2::direct<SubFsm2_::SubState2>,
SubFsm2::direct<SubFsm2_::SubState2b> > >,
_row < State1 , event4 , SubFsm2::entry_pt
<SubFsm2_::PseudoEntry1> >,
// +---------------------+--------+------------------------------------+-------+--------+
_row < SubFsm2 , event1 , State1 >,
_row < SubFsm2::exit_pt
<SubFsm2_::PseudoExit1>, event6 , State2 >
// +---------------------+--------+------------------------------------+-------+--------+
// Start Event Next Action Guard
// +---------------------+--------+-----------------------------------------------------+-------+--------+
_row < State1 , event1 , SubFsm2 >,
_row < State1 , event2 , typename SubFsm2::template direct<typename SubFsm2_::SubState2> >,
_row < State1 , event3 , mpl::vector<typename SubFsm2::template direct<typename SubFsm2_::SubState2>,
typename SubFsm2::template direct<typename SubFsm2_::SubState2b> > >,
_row < State1 , event4 , typename SubFsm2::template entry_pt
<typename SubFsm2_::PseudoEntry1> >,
// +---------------------+--------+-----------------------------------------------------+-------+--------+
_row < SubFsm2 , event1 , State1 >,
_row < typename SubFsm2::template exit_pt
<typename SubFsm2_::PseudoExit1>, event6 , State2 >
// +---------------------+--------+-----------------------------------------------------+-------+--------+
> {};
// Replaces the default no-transition response.
@@ -201,96 +207,107 @@ namespace
fsm.template get_state<Fsm_::SubFsm2&>().entry_counter=0;
fsm.template get_state<Fsm_::SubFsm2&>().exit_counter=0;
fsm.template get_state<Fsm_::SubFsm2&>().entry_action_counter=0;
fsm.template get_state<Fsm_::SubFsm2&>().template get_state<Fsm_::SubFsm2::SubState1&>().entry_counter=0;
fsm.template get_state<Fsm_::SubFsm2&>().template get_state<Fsm_::SubFsm2::SubState1&>().exit_counter=0;
fsm.template get_state<Fsm_::SubFsm2&>().template get_state<Fsm_::SubFsm2::SubState1b&>().entry_counter=0;
fsm.template get_state<Fsm_::SubFsm2&>().template get_state<Fsm_::SubFsm2::SubState1b&>().exit_counter=0;
fsm.template get_state<Fsm_::SubFsm2&>().template get_state<Fsm_::SubFsm2::SubState2&>().entry_counter=0;
fsm.template get_state<Fsm_::SubFsm2&>().template get_state<Fsm_::SubFsm2::SubState2&>().exit_counter=0;
fsm.template get_state<Fsm_::SubFsm2&>().template get_state<Fsm_::SubFsm2::SubState2b&>().entry_counter=0;
fsm.template get_state<Fsm_::SubFsm2&>().template get_state<Fsm_::SubFsm2::SubState2b&>().exit_counter=0;
fsm.template get_state<Fsm_::SubFsm2&>().template get_state<Fsm_::SubFsm2::SubState3&>().entry_counter=0;
fsm.template get_state<Fsm_::SubFsm2&>().template get_state<Fsm_::SubFsm2::SubState3&>().exit_counter=0;
fsm.template get_state<Fsm_::SubFsm2&>().template get_state<Fsm_::SubFsm2::PseudoEntry1&>().entry_counter=0;
fsm.template get_state<Fsm_::SubFsm2&>().template get_state<Fsm_::SubFsm2::PseudoEntry1&>().exit_counter=0;
fsm.template get_state<Fsm_::SubFsm2&>().template get_state<Fsm_::SubFsm2::exit_pt<SubFsm2_::PseudoExit1>&>().entry_counter=0;
fsm.template get_state<Fsm_::SubFsm2&>().template get_state<Fsm_::SubFsm2::exit_pt<SubFsm2_::PseudoExit1>&>().exit_counter=0;
fsm.template get_state<Fsm_::SubFsm2&>().template get_state<typename Fsm_::SubFsm2::SubState1&>().entry_counter=0;
fsm.template get_state<Fsm_::SubFsm2&>().template get_state<typename Fsm_::SubFsm2::SubState1&>().exit_counter=0;
fsm.template get_state<Fsm_::SubFsm2&>().template get_state<typename Fsm_::SubFsm2::SubState1b&>().entry_counter=0;
fsm.template get_state<Fsm_::SubFsm2&>().template get_state<typename Fsm_::SubFsm2::SubState1b&>().exit_counter=0;
fsm.template get_state<Fsm_::SubFsm2&>().template get_state<typename Fsm_::SubFsm2::SubState2&>().entry_counter=0;
fsm.template get_state<Fsm_::SubFsm2&>().template get_state<typename Fsm_::SubFsm2::SubState2&>().exit_counter=0;
fsm.template get_state<Fsm_::SubFsm2&>().template get_state<typename Fsm_::SubFsm2::SubState2b&>().entry_counter=0;
fsm.template get_state<Fsm_::SubFsm2&>().template get_state<typename Fsm_::SubFsm2::SubState2b&>().exit_counter=0;
fsm.template get_state<Fsm_::SubFsm2&>().template get_state<typename Fsm_::SubFsm2::SubState3&>().entry_counter=0;
fsm.template get_state<Fsm_::SubFsm2&>().template get_state<typename Fsm_::SubFsm2::SubState3&>().exit_counter=0;
fsm.template get_state<Fsm_::SubFsm2&>().template get_state<typename Fsm_::SubFsm2::PseudoEntry1&>().entry_counter=0;
fsm.template get_state<Fsm_::SubFsm2&>().template get_state<typename Fsm_::SubFsm2::PseudoEntry1&>().exit_counter=0;
fsm.template get_state<Fsm_::SubFsm2&>().template get_state<typename Fsm_::SubFsm2::template exit_pt<typename SubFsm2_::PseudoExit1>&>().entry_counter=0;
fsm.template get_state<Fsm_::SubFsm2&>().template get_state<typename Fsm_::SubFsm2::template exit_pt<typename SubFsm2_::PseudoExit1>&>().exit_counter=0;
}
};
typedef msm::back::state_machine<Fsm_> Fsm;
typedef Back<Fsm_, Policy> Fsm;
};
typedef boost::mpl::vector<
hierarchical_state_machine<boost::msm::back::state_machine>,
hierarchical_state_machine<boost::msm::back::state_machine, boost::msm::back::favor_compile_time>,
hierarchical_state_machine<boost::msm::back11::state_machine>
> test_machines;
// static char const* const state_names[] = { "State1", "SubFsm2","State2" };
BOOST_AUTO_TEST_CASE( entries_test )
BOOST_AUTO_TEST_CASE_TEMPLATE( entries_test, test_machine, test_machines )
{
Fsm p;
typename test_machine::Fsm p;
typedef typename test_machine::Fsm_ Fsm_;
p.start();
BOOST_CHECK_MESSAGE(p.get_state<Fsm_::State1&>().entry_counter == 1,"State1 entry not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<typename Fsm_::State1&>().entry_counter == 1,"State1 entry not called correctly");
p.process_event(event1());
p.process_event(event1());
BOOST_CHECK_MESSAGE(p.current_state()[0] == 0,"State1 should be active");
BOOST_CHECK_MESSAGE(p.get_state<Fsm_::State1&>().exit_counter == 1,"State1 exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<Fsm_::State1&>().entry_counter == 2,"State1 entry not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<Fsm_::SubFsm2&>().exit_counter == 1,"SubFsm2 exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<Fsm_::SubFsm2&>().entry_counter == 1,"SubFsm2 entry not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<typename Fsm_::State1&>().exit_counter == 1,"State1 exit not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<typename Fsm_::State1&>().entry_counter == 2,"State1 entry not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<typename Fsm_::SubFsm2&>().exit_counter == 1,"SubFsm2 exit not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<typename Fsm_::SubFsm2&>().entry_counter == 1,"SubFsm2 entry not called correctly");
p.process_event(event2());
p.process_event(event6());
p.process_event(event1());
BOOST_CHECK_MESSAGE(p.current_state()[0] == 0,"State1 should be active");
BOOST_CHECK_MESSAGE(p.get_state<Fsm_::State1&>().exit_counter == 2,"State1 exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<Fsm_::State1&>().entry_counter == 3,"State1 entry not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<Fsm_::SubFsm2&>().exit_counter == 2,"SubFsm2 exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<Fsm_::SubFsm2&>().entry_counter == 2,"SubFsm2 entry not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<Fsm_::SubFsm2&>().get_state<Fsm_::SubFsm2_::SubState2&>().entry_counter == 1,
BOOST_CHECK_MESSAGE(p.template get_state<typename Fsm_::State1&>().exit_counter == 2,"State1 exit not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<typename Fsm_::State1&>().entry_counter == 3,"State1 entry not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<typename Fsm_::SubFsm2&>().exit_counter == 2,"SubFsm2 exit not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<typename Fsm_::SubFsm2&>().entry_counter == 2,"SubFsm2 entry not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<typename Fsm_::SubFsm2&>().template get_state<typename Fsm_::SubFsm2_::SubState2&>().entry_counter == 1,
"SubFsm2::SubState2 entry not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<Fsm_::SubFsm2&>().get_state<Fsm_::SubFsm2_::SubState2&>().exit_counter == 1,
BOOST_CHECK_MESSAGE(p.template get_state<typename Fsm_::SubFsm2&>().template get_state<typename Fsm_::SubFsm2_::SubState2&>().exit_counter == 1,
"SubFsm2::SubState2 exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<Fsm_::SubFsm2&>().get_state<Fsm_::SubFsm2_::SubState1&>().entry_counter == 2,
BOOST_CHECK_MESSAGE(p.template get_state<typename Fsm_::SubFsm2&>().template get_state<typename Fsm_::SubFsm2_::SubState1&>().entry_counter == 2,
"SubFsm2::SubState1 entry not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<Fsm_::SubFsm2&>().get_state<Fsm_::SubFsm2_::SubState1&>().exit_counter == 2,
BOOST_CHECK_MESSAGE(p.template get_state<typename Fsm_::SubFsm2&>().template get_state<typename Fsm_::SubFsm2_::SubState1&>().exit_counter == 2,
"SubFsm2::SubState1 exit not called correctly");
p.process_event(event3());
p.process_event(event1());
BOOST_CHECK_MESSAGE(p.current_state()[0] == 0,"State1 should be active");
BOOST_CHECK_MESSAGE(p.get_state<Fsm_::State1&>().exit_counter == 3,"State1 exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<Fsm_::State1&>().entry_counter == 4,"State1 entry not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<Fsm_::SubFsm2&>().exit_counter == 3,"SubFsm2 exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<Fsm_::SubFsm2&>().entry_counter == 3,"SubFsm2 entry not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<Fsm_::SubFsm2&>().get_state<Fsm_::SubFsm2_::SubState2&>().entry_counter == 2,
BOOST_CHECK_MESSAGE(p.template get_state<typename Fsm_::State1&>().exit_counter == 3,"State1 exit not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<typename Fsm_::State1&>().entry_counter == 4,"State1 entry not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<typename Fsm_::SubFsm2&>().exit_counter == 3,"SubFsm2 exit not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<typename Fsm_::SubFsm2&>().entry_counter == 3,"SubFsm2 entry not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<typename Fsm_::SubFsm2&>().template get_state<typename Fsm_::SubFsm2_::SubState2&>().entry_counter == 2,
"SubFsm2::SubState2 entry not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<Fsm_::SubFsm2&>().get_state<Fsm_::SubFsm2_::SubState2&>().exit_counter == 2,
BOOST_CHECK_MESSAGE(p.template get_state<typename Fsm_::SubFsm2&>().template get_state<typename Fsm_::SubFsm2_::SubState2&>().exit_counter == 2,
"SubFsm2::SubState2 exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<Fsm_::SubFsm2&>().get_state<Fsm_::SubFsm2_::SubState2b&>().entry_counter == 1,
BOOST_CHECK_MESSAGE(p.template get_state<typename Fsm_::SubFsm2&>().template get_state<typename Fsm_::SubFsm2_::SubState2b&>().entry_counter == 1,
"SubFsm2::SubState2b entry not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<Fsm_::SubFsm2&>().get_state<Fsm_::SubFsm2_::SubState2b&>().exit_counter == 1,
BOOST_CHECK_MESSAGE(p.template get_state<typename Fsm_::SubFsm2&>().template get_state<typename Fsm_::SubFsm2_::SubState2b&>().exit_counter == 1,
"SubFsm2::SubState2b exit not called correctly");
p.process_event(event4());
p.process_event(event5());
BOOST_CHECK_MESSAGE(p.current_state()[0] == 2,"State2 should be active");
BOOST_CHECK_MESSAGE(p.get_state<Fsm_::State1&>().exit_counter == 4,"State1 exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<Fsm_::State2&>().entry_counter == 1,"State2 entry not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<Fsm_::SubFsm2&>().exit_counter == 4,"SubFsm2 exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<Fsm_::SubFsm2&>().entry_counter == 4,"SubFsm2 entry not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<Fsm_::SubFsm2&>().get_state<Fsm_::SubFsm2_::PseudoEntry1&>().entry_counter == 1,
BOOST_CHECK_MESSAGE(p.template get_state<typename Fsm_::State1&>().exit_counter == 4,"State1 exit not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<typename Fsm_::State2&>().entry_counter == 1,"State2 entry not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<typename Fsm_::SubFsm2&>().exit_counter == 4,"SubFsm2 exit not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<typename Fsm_::SubFsm2&>().entry_counter == 4,"SubFsm2 entry not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<typename Fsm_::SubFsm2&>().template get_state<typename Fsm_::SubFsm2_::PseudoEntry1&>().entry_counter == 1,
"SubFsm2::PseudoEntry1 entry not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<Fsm_::SubFsm2&>().get_state<Fsm_::SubFsm2_::PseudoEntry1&>().exit_counter == 1,
BOOST_CHECK_MESSAGE(p.template get_state<typename Fsm_::SubFsm2&>().template get_state<typename Fsm_::SubFsm2_::PseudoEntry1&>().exit_counter == 1,
"SubFsm2::PseudoEntry1 exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<Fsm_::SubFsm2&>().get_state<Fsm_::SubFsm2_::SubState3&>().entry_counter == 1,
BOOST_CHECK_MESSAGE(p.template get_state<typename Fsm_::SubFsm2&>().template get_state<typename Fsm_::SubFsm2_::SubState3&>().entry_counter == 1,
"SubFsm2::SubState3 entry not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<Fsm_::SubFsm2&>().get_state<Fsm_::SubFsm2_::SubState3&>().exit_counter == 1,
BOOST_CHECK_MESSAGE(p.template get_state<typename Fsm_::SubFsm2&>().template get_state<typename Fsm_::SubFsm2_::SubState3&>().exit_counter == 1,
"SubFsm2::SubState3 exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<Fsm_::SubFsm2&>().get_state<Fsm_::SubFsm2::exit_pt<Fsm_::SubFsm2_::PseudoExit1>&>().entry_counter == 1,
BOOST_CHECK_MESSAGE(p.template get_state<typename Fsm_::SubFsm2&>().template get_state<typename Fsm_::SubFsm2::template exit_pt<typename Fsm_::SubFsm2_::PseudoExit1>&>().entry_counter == 1,
"SubFsm2::PseudoExit1 entry not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<Fsm_::SubFsm2&>().get_state<Fsm_::SubFsm2::exit_pt<Fsm_::SubFsm2_::PseudoExit1>&>().exit_counter == 1,
BOOST_CHECK_MESSAGE(p.template get_state<typename Fsm_::SubFsm2&>().template get_state<typename Fsm_::SubFsm2::template exit_pt<typename Fsm_::SubFsm2_::PseudoExit1>&>().exit_counter == 1,
"SubFsm2::PseudoExit1 exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<Fsm_::SubFsm2&>().entry_action_counter == 1,"Action not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<typename Fsm_::SubFsm2&>().entry_action_counter == 1,"Action not called correctly");
}
}
using back0 = hierarchical_state_machine<boost::msm::back::state_machine, boost::msm::back::favor_compile_time>::Fsm;
using back1 = hierarchical_state_machine<boost::msm::back::state_machine, boost::msm::back::favor_compile_time>::Fsm_::SubFsm2;
BOOST_MSM_BACK_GENERATE_PROCESS_EVENT(back0);
BOOST_MSM_BACK_GENERATE_PROCESS_EVENT(back1);
+22 -22
View File
@@ -9,7 +9,7 @@
// http://www.boost.org/LICENSE_1_0.txt)
// back-end
#include <boost/msm/back/state_machine.hpp>
#include "BackCommon.hpp"
//front-end
#include <boost/msm/front/state_machine_def.hpp>
// functors
@@ -19,7 +19,7 @@
#include <boost/msm/front/euml/operator.hpp>
#ifndef BOOST_MSM_NONSTANDALONE_TEST
#define BOOST_TEST_MODULE MyTest
#define BOOST_TEST_MODULE event_queue_test
#endif
#include <boost/test/unit_test.hpp>
@@ -291,23 +291,23 @@ namespace
};
// Pick a back-end
typedef msm::back::state_machine<player_> player;
typedef get_test_machines<player_> players;
// static char const* const state_names[] = { "Stopped", "Open", "Empty", "Playing", "Paused" };
BOOST_AUTO_TEST_CASE( test_event_queue )
BOOST_AUTO_TEST_CASE_TEMPLATE( event_queue_test, player, players )
{
player p;
p.start();
BOOST_CHECK_MESSAGE(p.get_state<player_::Empty&>().entry_counter == 1,"Empty entry not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<player_::Empty&>().entry_counter == 1,"Empty entry not called correctly");
p.enqueue_event(open_close());
p.execute_single_queued_event();
BOOST_CHECK_MESSAGE(p.current_state()[0] == 1,"Open should be active"); //Open
BOOST_CHECK_MESSAGE(p.get_state<player_::Empty&>().exit_counter == 1,"Empty exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::Open&>().entry_counter == 1,"Open entry not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<player_::Empty&>().exit_counter == 1,"Empty exit not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<player_::Open&>().entry_counter == 1,"Open entry not called correctly");
p.enqueue_event(open_close());
p.enqueue_event(
@@ -318,42 +318,42 @@ namespace
BOOST_CHECK_MESSAGE(p.can_close_drawer_counter == 1,"guard not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::Open&>().exit_counter == 1,"Open exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::Empty&>().entry_counter == 2,"Empty entry not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<player_::Open&>().exit_counter == 1,"Open exit not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<player_::Empty&>().entry_counter == 2,"Empty entry not called correctly");
BOOST_CHECK_MESSAGE(p.current_state()[0] == 3,"Playing should be active"); //Playing
BOOST_CHECK_MESSAGE(p.get_state<player_::Empty&>().exit_counter == 2,"Empty exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::Stopped&>().entry_counter == 1,"Stopped entry not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::Stopped&>().exit_counter == 1,"Stopped exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::Playing&>().entry_counter == 1,"Playing entry not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<player_::Empty&>().exit_counter == 2,"Empty exit not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<player_::Stopped&>().entry_counter == 1,"Stopped entry not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<player_::Stopped&>().exit_counter == 1,"Stopped exit not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<player_::Playing&>().entry_counter == 1,"Playing entry not called correctly");
BOOST_CHECK_MESSAGE(p.start_playback_counter == 1,"action not called correctly");
BOOST_CHECK_MESSAGE(p.test_fct_counter == 1,"action not called correctly");
p.process_event(pause());
BOOST_CHECK_MESSAGE(p.current_state()[0] == 4,"Paused should be active"); //Paused
BOOST_CHECK_MESSAGE(p.get_state<player_::Playing&>().exit_counter == 1,"Playing exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::Paused&>().entry_counter == 1,"Paused entry not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<player_::Playing&>().exit_counter == 1,"Playing exit not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<player_::Paused&>().entry_counter == 1,"Paused entry not called correctly");
// go back to Playing
p.enqueue_event(end_pause());
p.execute_queued_events();
BOOST_CHECK_MESSAGE(p.current_state()[0] == 3,"Playing should be active"); //Playing
BOOST_CHECK_MESSAGE(p.get_state<player_::Paused&>().exit_counter == 1,"Paused exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::Playing&>().entry_counter == 2,"Playing entry not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<player_::Paused&>().exit_counter == 1,"Paused exit not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<player_::Playing&>().entry_counter == 2,"Playing entry not called correctly");
p.enqueue_event(pause());
p.enqueue_event(stop());
p.enqueue_event(stop());
p.execute_queued_events();
BOOST_CHECK_MESSAGE(p.get_state<player_::Playing&>().exit_counter == 2,"Playing exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::Paused&>().entry_counter == 2,"Paused entry not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<player_::Playing&>().exit_counter == 2,"Playing exit not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<player_::Paused&>().entry_counter == 2,"Paused entry not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::Paused&>().exit_counter == 2,"Paused exit not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<player_::Paused&>().exit_counter == 2,"Paused exit not called correctly");
BOOST_CHECK_MESSAGE(p.current_state()[0] == 0,"Stopped should be active"); //Stopped
BOOST_CHECK_MESSAGE(p.get_state<player_::Stopped&>().exit_counter == 2,"Stopped exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::Stopped&>().entry_counter == 3,"Stopped entry not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<player_::Stopped&>().exit_counter == 2,"Stopped exit not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<player_::Stopped&>().entry_counter == 3,"Stopped entry not called correctly");
}
}
+77 -59
View File
@@ -9,11 +9,11 @@
// http://www.boost.org/LICENSE_1_0.txt)
// back-end
#include <boost/msm/back/state_machine.hpp>
#include "BackCommon.hpp"
//front-end
#include <boost/msm/front/state_machine_def.hpp>
#ifndef BOOST_MSM_NONSTANDALONE_TEST
#define BOOST_TEST_MODULE MyTest
#define BOOST_TEST_MODULE history_test
#endif
#include <boost/test/unit_test.hpp>
@@ -38,9 +38,14 @@ namespace
std::string name;
};
template<template <typename...> class Back, typename Policy = void>
struct hierarchical_state_machine
{
// front-end: define the FSM structure
struct player_ : public msm::front::state_machine_def<player_>
{
BOOST_MSM_TEST_DEFINE_DEPENDENT_TEMPLATES(player_);
unsigned int start_playback_counter;
unsigned int can_close_drawer_counter;
@@ -81,6 +86,8 @@ namespace
struct Playing_ : public msm::front::state_machine_def<Playing_>
{
BOOST_MSM_TEST_DEFINE_DEPENDENT_TEMPLATES(Playing_);
template <class Event,class FSM>
void on_entry(Event const&,FSM& ) {++entry_counter;}
template <class Event,class FSM>
@@ -150,7 +157,7 @@ namespace
}
};
// back-end
typedef msm::back::state_machine<Playing_,msm::back::ShallowHistory<mpl::vector<end_pause> > > Playing;
typedef Back<Playing_,Policy,msm::back::ShallowHistory<mpl::vector<end_pause> > > Playing;
// state not defining any entry or exit
struct Paused : public msm::front::state<>
@@ -217,139 +224,150 @@ namespace
template <class Event,class FSM>
void on_entry(Event const&,FSM& fsm)
{
fsm.template get_state<player_::Stopped&>().entry_counter=0;
fsm.template get_state<player_::Stopped&>().exit_counter=0;
fsm.template get_state<player_::Open&>().entry_counter=0;
fsm.template get_state<player_::Open&>().exit_counter=0;
fsm.template get_state<player_::Empty&>().entry_counter=0;
fsm.template get_state<player_::Empty&>().exit_counter=0;
fsm.template get_state<player_::Playing&>().entry_counter=0;
fsm.template get_state<player_::Playing&>().exit_counter=0;
fsm.template get_state<player_::Playing&>().template get_state<player_::Playing::Song1&>().entry_counter=0;
fsm.template get_state<player_::Playing&>().template get_state<player_::Playing::Song1&>().exit_counter=0;
fsm.template get_state<player_::Playing&>().template get_state<player_::Playing::Song2&>().entry_counter=0;
fsm.template get_state<player_::Playing&>().template get_state<player_::Playing::Song2&>().exit_counter=0;
fsm.template get_state<player_::Playing&>().template get_state<player_::Playing::Song3&>().entry_counter=0;
fsm.template get_state<player_::Playing&>().template get_state<player_::Playing::Song3&>().exit_counter=0;
fsm.template get_state<player_::Paused&>().entry_counter=0;
fsm.template get_state<player_::Paused&>().exit_counter=0;
fsm.template get_state<typename player_::Stopped&>().entry_counter=0;
fsm.template get_state<typename player_::Stopped&>().exit_counter=0;
fsm.template get_state<typename player_::Open&>().entry_counter=0;
fsm.template get_state<typename player_::Open&>().exit_counter=0;
fsm.template get_state<typename player_::Empty&>().entry_counter=0;
fsm.template get_state<typename player_::Empty&>().exit_counter=0;
fsm.template get_state<typename player_::Playing&>().entry_counter=0;
fsm.template get_state<typename player_::Playing&>().exit_counter=0;
fsm.template get_state<typename player_::Playing&>().template get_state<typename player_::Playing::Song1&>().entry_counter=0;
fsm.template get_state<typename player_::Playing&>().template get_state<typename player_::Playing::Song1&>().exit_counter=0;
fsm.template get_state<typename player_::Playing&>().template get_state<typename player_::Playing::Song2&>().entry_counter=0;
fsm.template get_state<typename player_::Playing&>().template get_state<typename player_::Playing::Song2&>().exit_counter=0;
fsm.template get_state<typename player_::Playing&>().template get_state<typename player_::Playing::Song3&>().entry_counter=0;
fsm.template get_state<typename player_::Playing&>().template get_state<typename player_::Playing::Song3&>().exit_counter=0;
fsm.template get_state<typename player_::Paused&>().entry_counter=0;
fsm.template get_state<typename player_::Paused&>().exit_counter=0;
}
};
typedef Back<player_, Policy> player;
};
// Pick a back-end
typedef msm::back::state_machine<player_> player;
typedef boost::mpl::vector<
hierarchical_state_machine<boost::msm::back::state_machine>,
hierarchical_state_machine<boost::msm::back::state_machine, boost::msm::back::favor_compile_time>,
hierarchical_state_machine<boost::msm::back11::state_machine>
> test_machines;
// static char const* const state_names[] = { "Stopped", "Open", "Empty", "Playing", "Paused" };
BOOST_AUTO_TEST_CASE( my_test )
BOOST_AUTO_TEST_CASE_TEMPLATE( history_test, test_machine, test_machines )
{
player p;
typename test_machine::player p;
typedef typename test_machine::player_ player_;
p.start();
BOOST_CHECK_MESSAGE(p.get_state<player_::Empty&>().entry_counter == 1,"Empty entry not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<typename player_::Empty&>().entry_counter == 1,"Empty entry not called correctly");
p.process_event(open_close());
BOOST_CHECK_MESSAGE(p.current_state()[0] == 1,"Open should be active"); //Open
BOOST_CHECK_MESSAGE(p.get_state<player_::Empty&>().exit_counter == 1,"Empty exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::Open&>().entry_counter == 1,"Open entry not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<typename player_::Empty&>().exit_counter == 1,"Empty exit not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<typename player_::Open&>().entry_counter == 1,"Open entry not called correctly");
p.process_event(open_close());
BOOST_CHECK_MESSAGE(p.current_state()[0] == 2,"Empty should be active"); //Empty
BOOST_CHECK_MESSAGE(p.get_state<player_::Open&>().exit_counter == 1,"Open exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::Empty&>().entry_counter == 2,"Empty entry not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<typename player_::Open&>().exit_counter == 1,"Open exit not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<typename player_::Empty&>().entry_counter == 2,"Empty entry not called correctly");
BOOST_CHECK_MESSAGE(p.can_close_drawer_counter == 1,"guard not called correctly");
p.process_event(cd_detected("louie, louie"));
BOOST_CHECK_MESSAGE(p.current_state()[0] == 0,"Stopped should be active"); //Stopped
BOOST_CHECK_MESSAGE(p.get_state<player_::Empty&>().exit_counter == 2,"Empty exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::Stopped&>().entry_counter == 1,"Stopped entry not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<typename player_::Empty&>().exit_counter == 2,"Empty exit not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<typename player_::Stopped&>().entry_counter == 1,"Stopped entry not called correctly");
p.process_event(play());
BOOST_CHECK_MESSAGE(p.current_state()[0] == 3,"Playing should be active"); //Playing
BOOST_CHECK_MESSAGE(p.get_state<player_::Stopped&>().exit_counter == 1,"Stopped exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::Playing&>().entry_counter == 1,"Playing entry not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<typename player_::Stopped&>().exit_counter == 1,"Stopped exit not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<typename player_::Playing&>().entry_counter == 1,"Playing entry not called correctly");
BOOST_CHECK_MESSAGE(p.start_playback_counter == 1,"action not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::Playing&>().current_state()[0] == 0,"Song1 should be active");
BOOST_CHECK_MESSAGE(p.template get_state<typename player_::Playing&>().current_state()[0] == 0,"Song1 should be active");
BOOST_CHECK_MESSAGE(
p.get_state<player_::Playing&>().get_state<player_::Playing::Song1&>().entry_counter == 1,
p.template get_state<typename player_::Playing&>().template get_state<typename player_::Playing::Song1&>().entry_counter == 1,
"Song1 entry not called correctly");
p.process_event(NextSong());
BOOST_CHECK_MESSAGE(p.current_state()[0] == 3,"Playing should be active"); //Playing
BOOST_CHECK_MESSAGE(p.get_state<player_::Playing&>().current_state()[0] == 1,"Song2 should be active");
BOOST_CHECK_MESSAGE(p.template get_state<typename player_::Playing&>().current_state()[0] == 1,"Song2 should be active");
BOOST_CHECK_MESSAGE(
p.get_state<player_::Playing&>().get_state<player_::Playing::Song2&>().entry_counter == 1,
p.template get_state<typename player_::Playing&>().template get_state<typename player_::Playing::Song2&>().entry_counter == 1,
"Song2 entry not called correctly");
BOOST_CHECK_MESSAGE(
p.get_state<player_::Playing&>().get_state<player_::Playing::Song1&>().exit_counter == 1,
p.template get_state<typename player_::Playing&>().template get_state<typename player_::Playing::Song1&>().exit_counter == 1,
"Song1 exit not called correctly");
BOOST_CHECK_MESSAGE(
p.get_state<player_::Playing&>().start_next_song_counter == 0,
p.template get_state<typename player_::Playing&>().start_next_song_counter == 0,
"submachine action not called correctly");
p.process_event(NextSong());
BOOST_CHECK_MESSAGE(p.current_state()[0] == 3,"Playing should be active"); //Playing
BOOST_CHECK_MESSAGE(p.get_state<player_::Playing&>().current_state()[0] == 2,"Song3 should be active");
BOOST_CHECK_MESSAGE(p.template get_state<typename player_::Playing&>().current_state()[0] == 2,"Song3 should be active");
BOOST_CHECK_MESSAGE(
p.get_state<player_::Playing&>().get_state<player_::Playing::Song3&>().entry_counter == 1,
p.template get_state<typename player_::Playing&>().template get_state<typename player_::Playing::Song3&>().entry_counter == 1,
"Song3 entry not called correctly");
BOOST_CHECK_MESSAGE(
p.get_state<player_::Playing&>().get_state<player_::Playing::Song2&>().exit_counter == 1,
p.template get_state<typename player_::Playing&>().template get_state<typename player_::Playing::Song2&>().exit_counter == 1,
"Song2 exit not called correctly");
BOOST_CHECK_MESSAGE(
p.get_state<player_::Playing&>().start_next_song_counter == 1,
p.template get_state<typename player_::Playing&>().start_next_song_counter == 1,
"submachine action not called correctly");
p.process_event(PreviousSong());
BOOST_CHECK_MESSAGE(p.current_state()[0] == 3,"Playing should be active"); //Playing
BOOST_CHECK_MESSAGE(p.get_state<player_::Playing&>().current_state()[0] == 1,"Song2 should be active");
BOOST_CHECK_MESSAGE(p.template get_state<typename player_::Playing&>().current_state()[0] == 1,"Song2 should be active");
BOOST_CHECK_MESSAGE(
p.get_state<player_::Playing&>().get_state<player_::Playing::Song2&>().entry_counter == 2,
p.template get_state<typename player_::Playing&>().template get_state<typename player_::Playing::Song2&>().entry_counter == 2,
"Song2 entry not called correctly");
BOOST_CHECK_MESSAGE(
p.get_state<player_::Playing&>().get_state<player_::Playing::Song3&>().exit_counter == 1,
p.template get_state<typename player_::Playing&>().template get_state<typename player_::Playing::Song3&>().exit_counter == 1,
"Song3 exit not called correctly");
BOOST_CHECK_MESSAGE(
p.get_state<player_::Playing&>().start_prev_song_guard_counter == 1,
p.template get_state<typename player_::Playing&>().start_prev_song_guard_counter == 1,
"submachine guard not called correctly");
p.process_event(pause());
BOOST_CHECK_MESSAGE(p.current_state()[0] == 4,"Paused should be active"); //Paused
BOOST_CHECK_MESSAGE(p.get_state<player_::Playing&>().exit_counter == 1,"Playing exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::Paused&>().entry_counter == 1,"Paused entry not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<typename player_::Playing&>().exit_counter == 1,"Playing exit not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<typename player_::Paused&>().entry_counter == 1,"Paused entry not called correctly");
// go back to Playing
p.process_event(end_pause());
BOOST_CHECK_MESSAGE(p.current_state()[0] == 3,"Playing should be active"); //Playing
BOOST_CHECK_MESSAGE(p.get_state<player_::Paused&>().exit_counter == 1,"Paused exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::Playing&>().entry_counter == 2,"Playing entry not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::Playing&>().current_state()[0] == 1,"Song2 should be active");
BOOST_CHECK_MESSAGE(p.template get_state<typename player_::Paused&>().exit_counter == 1,"Paused exit not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<typename player_::Playing&>().entry_counter == 2,"Playing entry not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<typename player_::Playing&>().current_state()[0] == 1,"Song2 should be active");
BOOST_CHECK_MESSAGE(
p.get_state<player_::Playing&>().get_state<player_::Playing::Song2&>().entry_counter == 3,
p.template get_state<typename player_::Playing&>().template get_state<typename player_::Playing::Song2&>().entry_counter == 3,
"Song2 entry not called correctly");
p.process_event(pause());
BOOST_CHECK_MESSAGE(p.current_state()[0] == 4,"Paused should be active"); //Paused
BOOST_CHECK_MESSAGE(p.get_state<player_::Playing&>().exit_counter == 2,"Playing exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::Paused&>().entry_counter == 2,"Paused entry not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<typename player_::Playing&>().exit_counter == 2,"Playing exit not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<typename player_::Paused&>().entry_counter == 2,"Paused entry not called correctly");
p.process_event(stop());
BOOST_CHECK_MESSAGE(p.current_state()[0] == 0,"Stopped should be active"); //Stopped
BOOST_CHECK_MESSAGE(p.get_state<player_::Paused&>().exit_counter == 2,"Paused exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::Stopped&>().entry_counter == 2,"Stopped entry not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<typename player_::Paused&>().exit_counter == 2,"Paused exit not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<typename player_::Stopped&>().entry_counter == 2,"Stopped entry not called correctly");
p.process_event(stop());
BOOST_CHECK_MESSAGE(p.current_state()[0] == 0,"Stopped should be active"); //Stopped
BOOST_CHECK_MESSAGE(p.get_state<player_::Stopped&>().exit_counter == 2,"Stopped exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::Stopped&>().entry_counter == 3,"Stopped entry not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<typename player_::Stopped&>().exit_counter == 2,"Stopped exit not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<typename player_::Stopped&>().entry_counter == 3,"Stopped entry not called correctly");
p.process_event(play());
BOOST_CHECK_MESSAGE(p.get_state<player_::Playing&>().current_state()[0] == 0,"Song1 should be active");
BOOST_CHECK_MESSAGE(p.template get_state<typename player_::Playing&>().current_state()[0] == 0,"Song1 should be active");
BOOST_CHECK_MESSAGE(
p.get_state<player_::Playing&>().get_state<player_::Playing::Song1&>().entry_counter == 2,
p.template get_state<typename player_::Playing&>().template get_state<typename player_::Playing::Song1&>().entry_counter == 2,
"Song1 entry not called correctly");
}
}
using back0 = hierarchical_state_machine<boost::msm::back::state_machine, boost::msm::back::favor_compile_time>::player;
using back1 = hierarchical_state_machine<boost::msm::back::state_machine, boost::msm::back::favor_compile_time>::player_::Playing;
BOOST_MSM_BACK_GENERATE_PROCESS_EVENT(back0);
BOOST_MSM_BACK_GENERATE_PROCESS_EVENT(back1);
+13 -10
View File
@@ -12,7 +12,7 @@
#include <boost/fusion/include/std_tuple.hpp>
// back-end
#include <boost/msm/back/state_machine.hpp>
#include "BackCommon.hpp"
//front-end
#include <boost/msm/front/state_machine_def.hpp>
// functors
@@ -97,29 +97,32 @@ namespace
};
// Pick a back-end
typedef msm::back::state_machine<fsm_> Fsm;
typedef mpl::vector<
boost::msm::back::state_machine<fsm_>,
boost::msm::back11::state_machine<fsm_>
> Fsms;
BOOST_AUTO_TEST_CASE(kleene_deferred_test)
BOOST_AUTO_TEST_CASE_TEMPLATE(kleene_deferred_test, Fsm, Fsms)
{
Fsm fsm;
fsm.start();
BOOST_CHECK_MESSAGE(fsm.get_state<fsm_::StateA&>().entry_counter == 1,"StateA entry not called correctly");
BOOST_CHECK_MESSAGE(fsm.template get_state<fsm_::StateA&>().entry_counter == 1,"StateA entry not called correctly");
fsm.process_event(event1());
BOOST_CHECK_MESSAGE(fsm.current_state()[0] == 1,"StateB should be active");
BOOST_CHECK_MESSAGE(fsm.get_state<fsm_::StateA&>().exit_counter == 1,"StateA exit not called correctly");
BOOST_CHECK_MESSAGE(fsm.get_state<fsm_::StateB&>().entry_counter == 1,"StateB entry not called correctly");
BOOST_CHECK_MESSAGE(fsm.template get_state<fsm_::StateA&>().exit_counter == 1,"StateA exit not called correctly");
BOOST_CHECK_MESSAGE(fsm.template get_state<fsm_::StateB&>().entry_counter == 1,"StateB entry not called correctly");
fsm.process_event(event1());
BOOST_CHECK_MESSAGE(fsm.current_state()[0] == 1, "StateB should be active");
BOOST_CHECK_MESSAGE(fsm.get_state<fsm_::StateA&>().exit_counter == 1, "StateA exit not called correctly");
BOOST_CHECK_MESSAGE(fsm.get_state<fsm_::StateB&>().entry_counter == 1, "StateB entry not called correctly");
BOOST_CHECK_MESSAGE(fsm.template get_state<fsm_::StateA&>().exit_counter == 1, "StateA exit not called correctly");
BOOST_CHECK_MESSAGE(fsm.template get_state<fsm_::StateB&>().entry_counter == 1, "StateB entry not called correctly");
fsm.process_event(event2());
BOOST_CHECK_MESSAGE(fsm.current_state()[0] == 1, "StateB should be active");
BOOST_CHECK_MESSAGE(fsm.get_state<fsm_::StateA&>().exit_counter == 2, "StateA exit not called correctly");
BOOST_CHECK_MESSAGE(fsm.get_state<fsm_::StateB&>().entry_counter == 2, "StateB entry not called correctly");
BOOST_CHECK_MESSAGE(fsm.template get_state<fsm_::StateA&>().exit_counter == 2, "StateA exit not called correctly");
BOOST_CHECK_MESSAGE(fsm.template get_state<fsm_::StateB&>().entry_counter == 2, "StateB entry not called correctly");
}
}
+3 -3
View File
@@ -9,7 +9,7 @@
// http://www.boost.org/LICENSE_1_0.txt)
// back-end
#include <boost/msm/back/state_machine.hpp>
#include "BackCommon.hpp"
//front-end
#include <boost/msm/front/functor_row.hpp>
#include <boost/msm/front/state_machine_def.hpp>
@@ -87,10 +87,10 @@ namespace
};
// Pick a back-end
typedef msm::back::state_machine<Sm1_> Sm1;
typedef get_test_machines<Sm1_> Sm1s;
BOOST_AUTO_TEST_CASE(back_many_deferred_transitions)
BOOST_AUTO_TEST_CASE_TEMPLATE(back_many_deferred_transitions, Sm1, Sm1s)
{
Sm1 sm1;
sm1.start();
@@ -10,14 +10,14 @@
// back-end
#include <boost/msm/back11/state_machine.hpp>
#include "BackCommon.hpp"
//front-end
#include <boost/msm/front/state_machine_def.hpp>
#include <boost/msm/front/puml/puml.hpp>
#include <PumlCommon.hpp>
#include "PumlCommon.hpp"
#ifndef BOOST_MSM_NONSTANDALONE_TEST
#define BOOST_TEST_MODULE back11_only_string_puml_test
#define BOOST_TEST_MODULE only_string_puml_test
#endif
#include <boost/test/unit_test.hpp>
@@ -76,10 +76,10 @@ namespace
}
};
// Pick a back-end
typedef msm::back11::state_machine<player_> player;
typedef get_test_machines<player_> players;
BOOST_AUTO_TEST_CASE(back11_only_string_puml_test)
BOOST_AUTO_TEST_CASE_TEMPLATE(only_string_puml_test, player, players)
{
player p;
static_assert(msm::back11::get_number_of_regions<typename player::initial_state>::type::value == 1);
@@ -89,7 +89,7 @@ namespace
p.process_event(Event<by_name("open_close_")>{});
BOOST_CHECK_MESSAGE(p.current_state()[0] == 1,"Open should be active"); //Open
BOOST_CHECK_MESSAGE(p.is_flag_active<Flag<by_name("CDLoaded")>>() == false, "CDLoaded should not be active");
BOOST_CHECK_MESSAGE(p.template is_flag_active<Flag<by_name("CDLoaded")>>() == false, "CDLoaded should not be active");
p.process_event(Event<by_name("open_close_")>{});
BOOST_CHECK_MESSAGE(p.current_state()[0] == 2,"Empty should be active"); //Empty
@@ -105,13 +105,13 @@ namespace
BOOST_CHECK_MESSAGE(p.current_state()[0] == 3,"Playing should be active"); //Playing
BOOST_CHECK_MESSAGE(p.start_playback_counter == 1,"action not called correctly");
BOOST_CHECK_MESSAGE(p.test_fct_counter == 1,"action not called correctly");
BOOST_CHECK_MESSAGE(p.is_flag_active < Flag<by_name("CDLoaded")>>() == true, "CDLoaded should be active");
BOOST_CHECK_MESSAGE(p.template is_flag_active < Flag<by_name("CDLoaded")>>() == true, "CDLoaded should be active");
BOOST_CHECK_MESSAGE(p.entry_counter == 1, "Playing entry not called correctly");
BOOST_CHECK_MESSAGE(p.exit_counter == 0, "Playing exit not called correctly");
p.process_event(Event<by_name("pause_")>{});
BOOST_CHECK_MESSAGE(p.current_state()[0] == 4,"Paused should be active"); //Paused
BOOST_CHECK_MESSAGE(p.is_flag_active < Flag<by_name("CDLoaded")>>() == true, "CDLoaded should be active");
BOOST_CHECK_MESSAGE(p.template is_flag_active < Flag<by_name("CDLoaded")>>() == true, "CDLoaded should be active");
BOOST_CHECK_MESSAGE(p.entry_counter == 1, "Playing entry not called correctly");
BOOST_CHECK_MESSAGE(p.exit_counter == 1, "Playing exit not called correctly");
@@ -128,7 +128,7 @@ namespace
p.process_event(Event<by_name("stop_")>{});
BOOST_CHECK_MESSAGE(p.current_state()[0] == 0,"Stopped should be active"); //Stopped
BOOST_CHECK_MESSAGE(p.is_flag_active < Flag<by_name("CDLoaded")>>() == true, "CDLoaded should be active");
BOOST_CHECK_MESSAGE(p.template is_flag_active < Flag<by_name("CDLoaded")>>() == true, "CDLoaded should be active");
p.process_event(Event<by_name("stop_")>{});
BOOST_CHECK_MESSAGE(p.current_state()[0] == 0,"Stopped should be active"); //Stopped
+110 -91
View File
@@ -9,11 +9,11 @@
// http://www.boost.org/LICENSE_1_0.txt)
// back-end
#include <boost/msm/back/state_machine.hpp>
#include "BackCommon.hpp"
//front-end
#include <boost/msm/front/state_machine_def.hpp>
#ifndef BOOST_MSM_NONSTANDALONE_TEST
#define BOOST_TEST_MODULE MyTest
#define BOOST_TEST_MODULE orthogonal_deferred_test
#endif
#include <boost/test/unit_test.hpp>
@@ -49,9 +49,14 @@ namespace
std::string name;
};
template<template <typename...> class Back, typename Policy = void>
struct hierarchical_state_machine
{
// front-end: define the FSM structure
struct player_ : public msm::front::state_machine_def<player_>
{
BOOST_MSM_TEST_DEFINE_DEPENDENT_TEMPLATES(player_);
unsigned int start_playback_counter;
unsigned int can_close_drawer_counter;
unsigned int report_error_counter;
@@ -104,6 +109,8 @@ namespace
// by another team in another module. For simplicity I just declare it inside player
struct Playing_ : public msm::front::state_machine_def<Playing_>
{
BOOST_MSM_TEST_DEFINE_DEPENDENT_TEMPLATES(Playing_);
// when playing, the CD is loaded and we are in either pause or playing (duh)
typedef mpl::vector2<PlayingPaused,CDLoaded> flag_list;
@@ -178,7 +185,7 @@ namespace
}
};
// back-end
typedef msm::back::state_machine<Playing_> Playing;
typedef Back<Playing_, Policy> Playing;
// state not defining any entry or exit
struct Paused : public msm::front::state<>
@@ -282,206 +289,218 @@ namespace
template <class Event,class FSM>
void on_entry(Event const&,FSM& fsm)
{
fsm.template get_state<player_::Stopped&>().entry_counter=0;
fsm.template get_state<player_::Stopped&>().exit_counter=0;
fsm.template get_state<player_::Open&>().entry_counter=0;
fsm.template get_state<player_::Open&>().exit_counter=0;
fsm.template get_state<player_::Empty&>().entry_counter=0;
fsm.template get_state<player_::Empty&>().exit_counter=0;
fsm.template get_state<player_::Playing&>().entry_counter=0;
fsm.template get_state<player_::Playing&>().exit_counter=0;
fsm.template get_state<player_::Playing&>().template get_state<player_::Playing::Song1&>().entry_counter=0;
fsm.template get_state<player_::Playing&>().template get_state<player_::Playing::Song1&>().exit_counter=0;
fsm.template get_state<player_::Playing&>().template get_state<player_::Playing::Song2&>().entry_counter=0;
fsm.template get_state<player_::Playing&>().template get_state<player_::Playing::Song2&>().exit_counter=0;
fsm.template get_state<player_::Playing&>().template get_state<player_::Playing::Song3&>().entry_counter=0;
fsm.template get_state<player_::Playing&>().template get_state<player_::Playing::Song3&>().exit_counter=0;
fsm.template get_state<player_::Paused&>().entry_counter=0;
fsm.template get_state<player_::Paused&>().exit_counter=0;
fsm.template get_state<player_::AllOk&>().entry_counter=0;
fsm.template get_state<player_::AllOk&>().exit_counter=0;
fsm.template get_state<player_::ErrorMode&>().entry_counter=0;
fsm.template get_state<player_::ErrorMode&>().exit_counter=0;
fsm.template get_state<player_::ErrorTerminate&>().entry_counter=0;
fsm.template get_state<player_::ErrorTerminate&>().exit_counter=0;
fsm.template get_state<typename player_::Stopped&>().entry_counter=0;
fsm.template get_state<typename player_::Stopped&>().exit_counter=0;
fsm.template get_state<typename player_::Open&>().entry_counter=0;
fsm.template get_state<typename player_::Open&>().exit_counter=0;
fsm.template get_state<typename player_::Empty&>().entry_counter=0;
fsm.template get_state<typename player_::Empty&>().exit_counter=0;
fsm.template get_state<typename player_::Playing&>().entry_counter=0;
fsm.template get_state<typename player_::Playing&>().exit_counter=0;
fsm.template get_state<typename player_::Playing&>().template get_state<typename player_::Playing::Song1&>().entry_counter=0;
fsm.template get_state<typename player_::Playing&>().template get_state<typename player_::Playing::Song1&>().exit_counter=0;
fsm.template get_state<typename player_::Playing&>().template get_state<typename player_::Playing::Song2&>().entry_counter=0;
fsm.template get_state<typename player_::Playing&>().template get_state<typename player_::Playing::Song2&>().exit_counter=0;
fsm.template get_state<typename player_::Playing&>().template get_state<typename player_::Playing::Song3&>().entry_counter=0;
fsm.template get_state<typename player_::Playing&>().template get_state<typename player_::Playing::Song3&>().exit_counter=0;
fsm.template get_state<typename player_::Paused&>().entry_counter=0;
fsm.template get_state<typename player_::Paused&>().exit_counter=0;
fsm.template get_state<typename player_::AllOk&>().entry_counter=0;
fsm.template get_state<typename player_::AllOk&>().exit_counter=0;
fsm.template get_state<typename player_::ErrorMode&>().entry_counter=0;
fsm.template get_state<typename player_::ErrorMode&>().exit_counter=0;
fsm.template get_state<typename player_::ErrorTerminate&>().entry_counter=0;
fsm.template get_state<typename player_::ErrorTerminate&>().exit_counter=0;
}
};
typedef Back<player_, Policy> player;
};
// Pick a back-end
typedef msm::back::state_machine<player_> player;
typedef boost::mpl::vector<
hierarchical_state_machine<boost::msm::back::state_machine>,
hierarchical_state_machine<boost::msm::back::state_machine, boost::msm::back::favor_compile_time>,
hierarchical_state_machine<boost::msm::back11::state_machine>
> test_machines;
//static char const* const state_names[] = { "Stopped", "Open", "Empty", "Playing", "Paused","AllOk","ErrorMode" };
BOOST_AUTO_TEST_CASE( my_test )
BOOST_AUTO_TEST_CASE_TEMPLATE( orthogonal_deferred_test, test_machine, test_machines )
{
player p;
typename test_machine::player p;
typedef typename test_machine::player_ player_;
// needed to start the highest-level SM. This will call on_entry and mark the start of the SM
p.start();
// test deferred event
// deferred in Empty and Open, will be handled only after event cd_detected
p.process_event(play());
BOOST_CHECK_MESSAGE(p.current_state()[0] == 2,"Empty should be active"); //Empty
BOOST_CHECK_MESSAGE(p.get_state<player_::Open&>().exit_counter == 0,"Open exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::Playing&>().entry_counter == 0,"Playing entry not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::Empty&>().entry_counter == 1,"Empty entry not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<typename player_::Open&>().exit_counter == 0,"Open exit not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<typename player_::Playing&>().entry_counter == 0,"Playing entry not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<typename player_::Empty&>().entry_counter == 1,"Empty entry not called correctly");
//flags
BOOST_CHECK_MESSAGE(p.is_flag_active<CDLoaded>() == false,"CDLoaded should not be active");
BOOST_CHECK_MESSAGE(p.template is_flag_active<CDLoaded>() == false,"CDLoaded should not be active");
p.process_event(open_close());
BOOST_CHECK_MESSAGE(p.current_state()[0] == 1,"Open should be active"); //Open
BOOST_CHECK_MESSAGE(p.get_state<player_::Empty&>().exit_counter == 1,"Empty exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::Open&>().entry_counter == 1,"Open entry not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<typename player_::Empty&>().exit_counter == 1,"Empty exit not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<typename player_::Open&>().entry_counter == 1,"Open entry not called correctly");
p.process_event(open_close());
BOOST_CHECK_MESSAGE(p.current_state()[0] == 2,"Empty should be active"); //Empty
BOOST_CHECK_MESSAGE(p.get_state<player_::Open&>().exit_counter == 1,"Open exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::Empty&>().entry_counter == 2,"Empty entry not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<typename player_::Open&>().exit_counter == 1,"Open exit not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<typename player_::Empty&>().entry_counter == 2,"Empty entry not called correctly");
BOOST_CHECK_MESSAGE(p.can_close_drawer_counter == 1,"guard not called correctly");
//deferred event should have been processed
p.process_event(cd_detected("louie, louie"));
BOOST_CHECK_MESSAGE(p.current_state()[0] == 3,"Playing should be active"); //Playing
BOOST_CHECK_MESSAGE(p.get_state<player_::Empty&>().exit_counter == 2,"Empty exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::Stopped&>().entry_counter == 1,"Stopped entry not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::Stopped&>().exit_counter == 1,"Stopped exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::Playing&>().entry_counter == 1,"Playing entry not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<typename player_::Empty&>().exit_counter == 2,"Empty exit not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<typename player_::Stopped&>().entry_counter == 1,"Stopped entry not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<typename player_::Stopped&>().exit_counter == 1,"Stopped exit not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<typename player_::Playing&>().entry_counter == 1,"Playing entry not called correctly");
BOOST_CHECK_MESSAGE(p.start_playback_counter == 1,"action not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::Playing&>().current_state()[0] == 0,"Song1 should be active");
BOOST_CHECK_MESSAGE(p.template get_state<typename player_::Playing&>().current_state()[0] == 0,"Song1 should be active");
BOOST_CHECK_MESSAGE(
p.get_state<player_::Playing&>().get_state<player_::Playing::Song1&>().entry_counter == 1,
p.template get_state<typename player_::Playing&>().template get_state<typename player_::Playing::Song1&>().entry_counter == 1,
"Song1 entry not called correctly");
//flags
BOOST_CHECK_MESSAGE(p.is_flag_active<PlayingPaused>() == true,"PlayingPaused should be active");
BOOST_CHECK_MESSAGE(p.is_flag_active<FirstSongPlaying>() == true,"FirstSongPlaying should be active");
BOOST_CHECK_MESSAGE(p.template is_flag_active<PlayingPaused>() == true,"PlayingPaused should be active");
BOOST_CHECK_MESSAGE(p.template is_flag_active<FirstSongPlaying>() == true,"FirstSongPlaying should be active");
p.process_event(NextSong());
BOOST_CHECK_MESSAGE(p.current_state()[0] == 3,"Playing should be active"); //Playing
BOOST_CHECK_MESSAGE(p.get_state<player_::Playing&>().current_state()[0] == 1,"Song2 should be active");
BOOST_CHECK_MESSAGE(p.template get_state<typename player_::Playing&>().current_state()[0] == 1,"Song2 should be active");
BOOST_CHECK_MESSAGE(
p.get_state<player_::Playing&>().get_state<player_::Playing::Song2&>().entry_counter == 1,
p.template get_state<typename player_::Playing&>().template get_state<typename player_::Playing::Song2&>().entry_counter == 1,
"Song2 entry not called correctly");
BOOST_CHECK_MESSAGE(
p.get_state<player_::Playing&>().get_state<player_::Playing::Song1&>().exit_counter == 1,
p.template get_state<typename player_::Playing&>().template get_state<typename player_::Playing::Song1&>().exit_counter == 1,
"Song1 exit not called correctly");
BOOST_CHECK_MESSAGE(
p.get_state<player_::Playing&>().start_next_song_counter == 0,
p.template get_state<typename player_::Playing&>().start_next_song_counter == 0,
"submachine action not called correctly");
p.process_event(NextSong());
BOOST_CHECK_MESSAGE(p.current_state()[0] == 3,"Playing should be active"); //Playing
BOOST_CHECK_MESSAGE(p.get_state<player_::Playing&>().current_state()[0] == 2,"Song3 should be active");
BOOST_CHECK_MESSAGE(p.template get_state<typename player_::Playing&>().current_state()[0] == 2,"Song3 should be active");
BOOST_CHECK_MESSAGE(
p.get_state<player_::Playing&>().get_state<player_::Playing::Song3&>().entry_counter == 1,
p.template get_state<typename player_::Playing&>().template get_state<typename player_::Playing::Song3&>().entry_counter == 1,
"Song3 entry not called correctly");
BOOST_CHECK_MESSAGE(
p.get_state<player_::Playing&>().get_state<player_::Playing::Song2&>().exit_counter == 1,
p.template get_state<typename player_::Playing&>().template get_state<typename player_::Playing::Song2&>().exit_counter == 1,
"Song2 exit not called correctly");
BOOST_CHECK_MESSAGE(
p.get_state<player_::Playing&>().start_next_song_counter == 1,
p.template get_state<typename player_::Playing&>().start_next_song_counter == 1,
"submachine action not called correctly");
p.process_event(PreviousSong());
BOOST_CHECK_MESSAGE(p.current_state()[0] == 3,"Playing should be active"); //Playing
BOOST_CHECK_MESSAGE(p.get_state<player_::Playing&>().current_state()[0] == 1,"Song2 should be active");
BOOST_CHECK_MESSAGE(p.template get_state<typename player_::Playing&>().current_state()[0] == 1,"Song2 should be active");
BOOST_CHECK_MESSAGE(
p.get_state<player_::Playing&>().get_state<player_::Playing::Song2&>().entry_counter == 2,
p.template get_state<typename player_::Playing&>().template get_state<typename player_::Playing::Song2&>().entry_counter == 2,
"Song2 entry not called correctly");
BOOST_CHECK_MESSAGE(
p.get_state<player_::Playing&>().get_state<player_::Playing::Song3&>().exit_counter == 1,
p.template get_state<typename player_::Playing&>().template get_state<typename player_::Playing::Song3&>().exit_counter == 1,
"Song3 exit not called correctly");
BOOST_CHECK_MESSAGE(
p.get_state<player_::Playing&>().start_prev_song_guard_counter == 1,
p.template get_state<typename player_::Playing&>().start_prev_song_guard_counter == 1,
"submachine guard not called correctly");
//flags
BOOST_CHECK_MESSAGE(p.is_flag_active<PlayingPaused>() == true,"PlayingPaused should be active");
BOOST_CHECK_MESSAGE(p.is_flag_active<FirstSongPlaying>() == false,"FirstSongPlaying should not be active");
BOOST_CHECK_MESSAGE(p.template is_flag_active<PlayingPaused>() == true,"PlayingPaused should be active");
BOOST_CHECK_MESSAGE(p.template is_flag_active<FirstSongPlaying>() == false,"FirstSongPlaying should not be active");
p.process_event(pause());
BOOST_CHECK_MESSAGE(p.current_state()[0] == 4,"Paused should be active"); //Paused
BOOST_CHECK_MESSAGE(p.get_state<player_::Playing&>().exit_counter == 1,"Playing exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::Paused&>().entry_counter == 1,"Paused entry not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<typename player_::Playing&>().exit_counter == 1,"Playing exit not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<typename player_::Paused&>().entry_counter == 1,"Paused entry not called correctly");
//flags
BOOST_CHECK_MESSAGE(p.is_flag_active<PlayingPaused>() == true,"PlayingPaused should be active");
BOOST_CHECK_MESSAGE(p.template is_flag_active<PlayingPaused>() == true,"PlayingPaused should be active");
// go back to Playing
p.process_event(end_pause());
BOOST_CHECK_MESSAGE(p.current_state()[0] == 3,"Playing should be active"); //Playing
BOOST_CHECK_MESSAGE(p.get_state<player_::Paused&>().exit_counter == 1,"Paused exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::Playing&>().entry_counter == 2,"Playing entry not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<typename player_::Paused&>().exit_counter == 1,"Paused exit not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<typename player_::Playing&>().entry_counter == 2,"Playing entry not called correctly");
p.process_event(pause());
BOOST_CHECK_MESSAGE(p.current_state()[0] == 4,"Paused should be active"); //Paused
BOOST_CHECK_MESSAGE(p.get_state<player_::Playing&>().exit_counter == 2,"Playing exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::Paused&>().entry_counter == 2,"Paused entry not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<typename player_::Playing&>().exit_counter == 2,"Playing exit not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<typename player_::Paused&>().entry_counter == 2,"Paused entry not called correctly");
p.process_event(stop());
BOOST_CHECK_MESSAGE(p.current_state()[0] == 0,"Stopped should be active"); //Stopped
BOOST_CHECK_MESSAGE(p.get_state<player_::Paused&>().exit_counter == 2,"Paused exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::Stopped&>().entry_counter == 2,"Stopped entry not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<typename player_::Paused&>().exit_counter == 2,"Paused exit not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<typename player_::Stopped&>().entry_counter == 2,"Stopped entry not called correctly");
//flags
BOOST_CHECK_MESSAGE(p.is_flag_active<PlayingPaused>() == false,"PlayingPaused should not be active");
BOOST_CHECK_MESSAGE(p.is_flag_active<CDLoaded>() == true,"CDLoaded should be active");
//BOOST_CHECK_MESSAGE(p.is_flag_active<CDLoaded,player::Flag_AND>() == false,"CDLoaded with AND should not be active");
BOOST_CHECK_MESSAGE(p.template is_flag_active<PlayingPaused>() == false,"PlayingPaused should not be active");
BOOST_CHECK_MESSAGE(p.template is_flag_active<CDLoaded>() == true,"CDLoaded should be active");
//BOOST_CHECK_MESSAGE(p.template is_flag_active<CDLoaded,player::Flag_AND>() == false,"CDLoaded with AND should not be active");
p.process_event(stop());
BOOST_CHECK_MESSAGE(p.current_state()[0] == 0,"Stopped should be active"); //Stopped
BOOST_CHECK_MESSAGE(p.get_state<player_::Stopped&>().exit_counter == 2,"Stopped exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::Stopped&>().entry_counter == 3,"Stopped entry not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<typename player_::Stopped&>().exit_counter == 2,"Stopped exit not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<typename player_::Stopped&>().entry_counter == 3,"Stopped entry not called correctly");
//test interrupt
BOOST_CHECK_MESSAGE(p.current_state()[1] == 5,"AllOk should be active"); //AllOk
p.process_event(error_found());
BOOST_CHECK_MESSAGE(p.current_state()[1] == 6,"ErrorMode should be active"); //ErrorMode
BOOST_CHECK_MESSAGE(p.get_state<player_::AllOk&>().exit_counter == 1,"AllOk exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::ErrorMode&>().entry_counter == 1,"ErrorMode entry not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<typename player_::AllOk&>().exit_counter == 1,"AllOk exit not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<typename player_::ErrorMode&>().entry_counter == 1,"ErrorMode entry not called correctly");
// try generating more events
p.process_event(play());
BOOST_CHECK_MESSAGE(p.current_state()[1] == 6,"ErrorMode should be active"); //ErrorMode
BOOST_CHECK_MESSAGE(p.get_state<player_::AllOk&>().exit_counter == 1,"AllOk exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::ErrorMode&>().entry_counter == 1,"ErrorMode entry not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<typename player_::AllOk&>().exit_counter == 1,"AllOk exit not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<typename player_::ErrorMode&>().entry_counter == 1,"ErrorMode entry not called correctly");
BOOST_CHECK_MESSAGE(p.current_state()[0] == 0,"Stopped should be active"); //Stopped
BOOST_CHECK_MESSAGE(p.get_state<player_::Stopped&>().exit_counter == 2,"Stopped exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::Stopped&>().entry_counter == 3,"Stopped entry not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<typename player_::Stopped&>().exit_counter == 2,"Stopped exit not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<typename player_::Stopped&>().entry_counter == 3,"Stopped entry not called correctly");
p.process_event(end_error());
BOOST_CHECK_MESSAGE(p.current_state()[1] == 5,"AllOk should be active"); //AllOk
BOOST_CHECK_MESSAGE(p.get_state<player_::ErrorMode&>().exit_counter == 1,"ErrorMode exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::AllOk&>().entry_counter == 2,"AllOk entry not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<typename player_::ErrorMode&>().exit_counter == 1,"ErrorMode exit not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<typename player_::AllOk&>().entry_counter == 2,"AllOk entry not called correctly");
p.process_event(play());
BOOST_CHECK_MESSAGE(p.current_state()[0] == 3,"Playing should be active"); //Playing
BOOST_CHECK_MESSAGE(p.get_state<player_::Stopped&>().exit_counter == 3,"Stopped exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::Playing&>().entry_counter == 3,"Playing entry not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<typename player_::Stopped&>().exit_counter == 3,"Stopped exit not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<typename player_::Playing&>().entry_counter == 3,"Playing entry not called correctly");
//test terminate
BOOST_CHECK_MESSAGE(p.current_state()[1] == 5,"AllOk should be active"); //AllOk
p.process_event(do_terminate());
BOOST_CHECK_MESSAGE(p.current_state()[1] == 7,"ErrorTerminate should be active"); //ErrorTerminate
BOOST_CHECK_MESSAGE(p.get_state<player_::AllOk&>().exit_counter == 2,"AllOk exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::ErrorTerminate&>().entry_counter == 1,"ErrorTerminate entry not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<typename player_::AllOk&>().exit_counter == 2,"AllOk exit not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<typename player_::ErrorTerminate&>().entry_counter == 1,"ErrorTerminate entry not called correctly");
// try generating more events
p.process_event(stop());
BOOST_CHECK_MESSAGE(p.current_state()[1] == 7,"ErrorTerminate should be active"); //ErrorTerminate
BOOST_CHECK_MESSAGE(p.get_state<player_::ErrorTerminate&>().exit_counter == 0,"ErrorTerminate exit not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<typename player_::ErrorTerminate&>().exit_counter == 0,"ErrorTerminate exit not called correctly");
BOOST_CHECK_MESSAGE(p.current_state()[0] == 3,"Playing should be active"); //Playing
BOOST_CHECK_MESSAGE(p.get_state<player_::Playing&>().exit_counter == 2,"Playing exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::Stopped&>().entry_counter == 3,"Stopped entry not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<typename player_::Playing&>().exit_counter == 2,"Playing exit not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<typename player_::Stopped&>().entry_counter == 3,"Stopped entry not called correctly");
p.process_event(end_error());
BOOST_CHECK_MESSAGE(p.current_state()[1] == 7,"ErrorTerminate should be active"); //ErrorTerminate
BOOST_CHECK_MESSAGE(p.current_state()[0] == 3,"Playing should be active"); //Playing
BOOST_CHECK_MESSAGE(p.get_state<player_::Playing&>().exit_counter == 2,"Playing exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::Stopped&>().entry_counter == 3,"Stopped entry not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<typename player_::Playing&>().exit_counter == 2,"Playing exit not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<typename player_::Stopped&>().entry_counter == 3,"Stopped entry not called correctly");
p.process_event(stop());
BOOST_CHECK_MESSAGE(p.current_state()[1] == 7,"ErrorTerminate should be active"); //ErrorTerminate
BOOST_CHECK_MESSAGE(p.current_state()[0] == 3,"Playing should be active"); //Playing
BOOST_CHECK_MESSAGE(p.get_state<player_::Playing&>().exit_counter == 2,"Playing exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::Stopped&>().entry_counter == 3,"Stopped entry not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<typename player_::Playing&>().exit_counter == 2,"Playing exit not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<typename player_::Stopped&>().entry_counter == 3,"Stopped entry not called correctly");
}
}
using back0 = hierarchical_state_machine<boost::msm::back::state_machine, boost::msm::back::favor_compile_time>::player;
using back1 = hierarchical_state_machine<boost::msm::back::state_machine, boost::msm::back::favor_compile_time>::player_::Playing;
BOOST_MSM_BACK_GENERATE_PROCESS_EVENT(back0);
BOOST_MSM_BACK_GENERATE_PROCESS_EVENT(back1);
+110 -91
View File
@@ -9,13 +9,13 @@
// http://www.boost.org/LICENSE_1_0.txt)
// back-end
#include <boost/msm/back/state_machine.hpp>
#include "BackCommon.hpp"
//front-end
#include <boost/msm/front/state_machine_def.hpp>
#include <boost/msm/front/functor_row.hpp>
#ifndef BOOST_MSM_NONSTANDALONE_TEST
#define BOOST_TEST_MODULE MyTest
#define BOOST_TEST_MODULE orthogonal_deferred_2_test
#endif
#include <boost/test/unit_test.hpp>
@@ -52,9 +52,14 @@ namespace
std::string name;
};
template<template <typename...> class Back, typename Policy = void>
struct hierarchical_state_machine
{
// front-end: define the FSM structure
struct player_ : public msm::front::state_machine_def<player_>
{
BOOST_MSM_TEST_DEFINE_DEPENDENT_TEMPLATES(player_);
// we want deferred events and no state requires deferred events (only the fsm in the
// transition table), so the fsm does.
typedef int activate_deferred_events;
@@ -109,6 +114,8 @@ namespace
// by another team in another module. For simplicity I just declare it inside player
struct Playing_ : public msm::front::state_machine_def<Playing_>
{
BOOST_MSM_TEST_DEFINE_DEPENDENT_TEMPLATES(Playing_);
// when playing, the CD is loaded and we are in either pause or playing (duh)
typedef mpl::vector2<PlayingPaused,CDLoaded> flag_list;
@@ -183,7 +190,7 @@ namespace
}
};
// back-end
typedef msm::back::state_machine<Playing_> Playing;
typedef Back<Playing_, Policy> Playing;
// state not defining any entry or exit
struct Paused : public msm::front::state<>
@@ -289,206 +296,218 @@ namespace
template <class Event,class FSM>
void on_entry(Event const&,FSM& fsm)
{
fsm.template get_state<player_::Stopped&>().entry_counter=0;
fsm.template get_state<player_::Stopped&>().exit_counter=0;
fsm.template get_state<player_::Open&>().entry_counter=0;
fsm.template get_state<player_::Open&>().exit_counter=0;
fsm.template get_state<player_::Empty&>().entry_counter=0;
fsm.template get_state<player_::Empty&>().exit_counter=0;
fsm.template get_state<player_::Playing&>().entry_counter=0;
fsm.template get_state<player_::Playing&>().exit_counter=0;
fsm.template get_state<player_::Playing&>().template get_state<player_::Playing::Song1&>().entry_counter=0;
fsm.template get_state<player_::Playing&>().template get_state<player_::Playing::Song1&>().exit_counter=0;
fsm.template get_state<player_::Playing&>().template get_state<player_::Playing::Song2&>().entry_counter=0;
fsm.template get_state<player_::Playing&>().template get_state<player_::Playing::Song2&>().exit_counter=0;
fsm.template get_state<player_::Playing&>().template get_state<player_::Playing::Song3&>().entry_counter=0;
fsm.template get_state<player_::Playing&>().template get_state<player_::Playing::Song3&>().exit_counter=0;
fsm.template get_state<player_::Paused&>().entry_counter=0;
fsm.template get_state<player_::Paused&>().exit_counter=0;
fsm.template get_state<player_::AllOk&>().entry_counter=0;
fsm.template get_state<player_::AllOk&>().exit_counter=0;
fsm.template get_state<player_::ErrorMode&>().entry_counter=0;
fsm.template get_state<player_::ErrorMode&>().exit_counter=0;
fsm.template get_state<player_::ErrorTerminate&>().entry_counter=0;
fsm.template get_state<player_::ErrorTerminate&>().exit_counter=0;
fsm.template get_state<typename player_::Stopped&>().entry_counter=0;
fsm.template get_state<typename player_::Stopped&>().exit_counter=0;
fsm.template get_state<typename player_::Open&>().entry_counter=0;
fsm.template get_state<typename player_::Open&>().exit_counter=0;
fsm.template get_state<typename player_::Empty&>().entry_counter=0;
fsm.template get_state<typename player_::Empty&>().exit_counter=0;
fsm.template get_state<typename player_::Playing&>().entry_counter=0;
fsm.template get_state<typename player_::Playing&>().exit_counter=0;
fsm.template get_state<typename player_::Playing&>().template get_state<typename player_::Playing::Song1&>().entry_counter=0;
fsm.template get_state<typename player_::Playing&>().template get_state<typename player_::Playing::Song1&>().exit_counter=0;
fsm.template get_state<typename player_::Playing&>().template get_state<typename player_::Playing::Song2&>().entry_counter=0;
fsm.template get_state<typename player_::Playing&>().template get_state<typename player_::Playing::Song2&>().exit_counter=0;
fsm.template get_state<typename player_::Playing&>().template get_state<typename player_::Playing::Song3&>().entry_counter=0;
fsm.template get_state<typename player_::Playing&>().template get_state<typename player_::Playing::Song3&>().exit_counter=0;
fsm.template get_state<typename player_::Paused&>().entry_counter=0;
fsm.template get_state<typename player_::Paused&>().exit_counter=0;
fsm.template get_state<typename player_::AllOk&>().entry_counter=0;
fsm.template get_state<typename player_::AllOk&>().exit_counter=0;
fsm.template get_state<typename player_::ErrorMode&>().entry_counter=0;
fsm.template get_state<typename player_::ErrorMode&>().exit_counter=0;
fsm.template get_state<typename player_::ErrorTerminate&>().entry_counter=0;
fsm.template get_state<typename player_::ErrorTerminate&>().exit_counter=0;
}
};
typedef Back<player_, Policy> player;
};
// Pick a back-end
typedef msm::back::state_machine<player_> player;
typedef boost::mpl::vector<
hierarchical_state_machine<boost::msm::back::state_machine>,
hierarchical_state_machine<boost::msm::back::state_machine, boost::msm::back::favor_compile_time>,
hierarchical_state_machine<boost::msm::back11::state_machine>
> test_machines;
//static char const* const state_names[] = { "Stopped", "Open", "Empty", "Playing", "Paused","AllOk","ErrorMode" };
BOOST_AUTO_TEST_CASE( my_test )
BOOST_AUTO_TEST_CASE_TEMPLATE( orthogonal_deferred_2_test, test_machine, test_machines )
{
player p;
typename test_machine::player p;
typedef typename test_machine::player_ player_;
// needed to start the highest-level SM. This will call on_entry and mark the start of the SM
p.start();
// test deferred event
// deferred in Empty and Open, will be handled only after event cd_detected
p.process_event(play());
BOOST_CHECK_MESSAGE(p.current_state()[0] == 2,"Empty should be active"); //Empty
BOOST_CHECK_MESSAGE(p.get_state<player_::Open&>().exit_counter == 0,"Open exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::Playing&>().entry_counter == 0,"Playing entry not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::Empty&>().entry_counter == 1,"Empty entry not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<typename player_::Open&>().exit_counter == 0,"Open exit not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<typename player_::Playing&>().entry_counter == 0,"Playing entry not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<typename player_::Empty&>().entry_counter == 1,"Empty entry not called correctly");
//flags
BOOST_CHECK_MESSAGE(p.is_flag_active<CDLoaded>() == false,"CDLoaded should not be active");
BOOST_CHECK_MESSAGE(p.template is_flag_active<CDLoaded>() == false,"CDLoaded should not be active");
p.process_event(open_close());
BOOST_CHECK_MESSAGE(p.current_state()[0] == 1,"Open should be active"); //Open
BOOST_CHECK_MESSAGE(p.get_state<player_::Empty&>().exit_counter == 1,"Empty exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::Open&>().entry_counter == 1,"Open entry not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<typename player_::Empty&>().exit_counter == 1,"Empty exit not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<typename player_::Open&>().entry_counter == 1,"Open entry not called correctly");
p.process_event(open_close());
BOOST_CHECK_MESSAGE(p.current_state()[0] == 2,"Empty should be active"); //Empty
BOOST_CHECK_MESSAGE(p.get_state<player_::Open&>().exit_counter == 1,"Open exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::Empty&>().entry_counter == 2,"Empty entry not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<typename player_::Open&>().exit_counter == 1,"Open exit not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<typename player_::Empty&>().entry_counter == 2,"Empty entry not called correctly");
BOOST_CHECK_MESSAGE(p.can_close_drawer_counter == 1,"guard not called correctly");
//deferred event should have been processed
p.process_event(cd_detected("louie, louie"));
BOOST_CHECK_MESSAGE(p.current_state()[0] == 3,"Playing should be active"); //Playing
BOOST_CHECK_MESSAGE(p.get_state<player_::Empty&>().exit_counter == 2,"Empty exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::Stopped&>().entry_counter == 1,"Stopped entry not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::Stopped&>().exit_counter == 1,"Stopped exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::Playing&>().entry_counter == 1,"Playing entry not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<typename player_::Empty&>().exit_counter == 2,"Empty exit not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<typename player_::Stopped&>().entry_counter == 1,"Stopped entry not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<typename player_::Stopped&>().exit_counter == 1,"Stopped exit not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<typename player_::Playing&>().entry_counter == 1,"Playing entry not called correctly");
BOOST_CHECK_MESSAGE(p.start_playback_counter == 1,"action not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::Playing&>().current_state()[0] == 0,"Song1 should be active");
BOOST_CHECK_MESSAGE(p.template get_state<typename player_::Playing&>().current_state()[0] == 0,"Song1 should be active");
BOOST_CHECK_MESSAGE(
p.get_state<player_::Playing&>().get_state<player_::Playing::Song1&>().entry_counter == 1,
p.template get_state<typename player_::Playing&>().template get_state<typename player_::Playing::Song1&>().entry_counter == 1,
"Song1 entry not called correctly");
//flags
BOOST_CHECK_MESSAGE(p.is_flag_active<PlayingPaused>() == true,"PlayingPaused should be active");
BOOST_CHECK_MESSAGE(p.is_flag_active<FirstSongPlaying>() == true,"FirstSongPlaying should be active");
BOOST_CHECK_MESSAGE(p.template is_flag_active<PlayingPaused>() == true,"PlayingPaused should be active");
BOOST_CHECK_MESSAGE(p.template is_flag_active<FirstSongPlaying>() == true,"FirstSongPlaying should be active");
p.process_event(NextSong());
BOOST_CHECK_MESSAGE(p.current_state()[0] == 3,"Playing should be active"); //Playing
BOOST_CHECK_MESSAGE(p.get_state<player_::Playing&>().current_state()[0] == 1,"Song2 should be active");
BOOST_CHECK_MESSAGE(p.template get_state<typename player_::Playing&>().current_state()[0] == 1,"Song2 should be active");
BOOST_CHECK_MESSAGE(
p.get_state<player_::Playing&>().get_state<player_::Playing::Song2&>().entry_counter == 1,
p.template get_state<typename player_::Playing&>().template get_state<typename player_::Playing::Song2&>().entry_counter == 1,
"Song2 entry not called correctly");
BOOST_CHECK_MESSAGE(
p.get_state<player_::Playing&>().get_state<player_::Playing::Song1&>().exit_counter == 1,
p.template get_state<typename player_::Playing&>().template get_state<typename player_::Playing::Song1&>().exit_counter == 1,
"Song1 exit not called correctly");
BOOST_CHECK_MESSAGE(
p.get_state<player_::Playing&>().start_next_song_counter == 0,
p.template get_state<typename player_::Playing&>().start_next_song_counter == 0,
"submachine action not called correctly");
p.process_event(NextSong());
BOOST_CHECK_MESSAGE(p.current_state()[0] == 3,"Playing should be active"); //Playing
BOOST_CHECK_MESSAGE(p.get_state<player_::Playing&>().current_state()[0] == 2,"Song3 should be active");
BOOST_CHECK_MESSAGE(p.template get_state<typename player_::Playing&>().current_state()[0] == 2,"Song3 should be active");
BOOST_CHECK_MESSAGE(
p.get_state<player_::Playing&>().get_state<player_::Playing::Song3&>().entry_counter == 1,
p.template get_state<typename player_::Playing&>().template get_state<typename player_::Playing::Song3&>().entry_counter == 1,
"Song3 entry not called correctly");
BOOST_CHECK_MESSAGE(
p.get_state<player_::Playing&>().get_state<player_::Playing::Song2&>().exit_counter == 1,
p.template get_state<typename player_::Playing&>().template get_state<typename player_::Playing::Song2&>().exit_counter == 1,
"Song2 exit not called correctly");
BOOST_CHECK_MESSAGE(
p.get_state<player_::Playing&>().start_next_song_counter == 1,
p.template get_state<typename player_::Playing&>().start_next_song_counter == 1,
"submachine action not called correctly");
p.process_event(PreviousSong());
BOOST_CHECK_MESSAGE(p.current_state()[0] == 3,"Playing should be active"); //Playing
BOOST_CHECK_MESSAGE(p.get_state<player_::Playing&>().current_state()[0] == 1,"Song2 should be active");
BOOST_CHECK_MESSAGE(p.template get_state<typename player_::Playing&>().current_state()[0] == 1,"Song2 should be active");
BOOST_CHECK_MESSAGE(
p.get_state<player_::Playing&>().get_state<player_::Playing::Song2&>().entry_counter == 2,
p.template get_state<typename player_::Playing&>().template get_state<typename player_::Playing::Song2&>().entry_counter == 2,
"Song2 entry not called correctly");
BOOST_CHECK_MESSAGE(
p.get_state<player_::Playing&>().get_state<player_::Playing::Song3&>().exit_counter == 1,
p.template get_state<typename player_::Playing&>().template get_state<typename player_::Playing::Song3&>().exit_counter == 1,
"Song3 exit not called correctly");
BOOST_CHECK_MESSAGE(
p.get_state<player_::Playing&>().start_prev_song_guard_counter == 1,
p.template get_state<typename player_::Playing&>().start_prev_song_guard_counter == 1,
"submachine guard not called correctly");
//flags
BOOST_CHECK_MESSAGE(p.is_flag_active<PlayingPaused>() == true,"PlayingPaused should be active");
BOOST_CHECK_MESSAGE(p.is_flag_active<FirstSongPlaying>() == false,"FirstSongPlaying should not be active");
BOOST_CHECK_MESSAGE(p.template is_flag_active<PlayingPaused>() == true,"PlayingPaused should be active");
BOOST_CHECK_MESSAGE(p.template is_flag_active<FirstSongPlaying>() == false,"FirstSongPlaying should not be active");
p.process_event(pause());
BOOST_CHECK_MESSAGE(p.current_state()[0] == 4,"Paused should be active"); //Paused
BOOST_CHECK_MESSAGE(p.get_state<player_::Playing&>().exit_counter == 1,"Playing exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::Paused&>().entry_counter == 1,"Paused entry not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<typename player_::Playing&>().exit_counter == 1,"Playing exit not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<typename player_::Paused&>().entry_counter == 1,"Paused entry not called correctly");
//flags
BOOST_CHECK_MESSAGE(p.is_flag_active<PlayingPaused>() == true,"PlayingPaused should be active");
BOOST_CHECK_MESSAGE(p.template is_flag_active<PlayingPaused>() == true,"PlayingPaused should be active");
// go back to Playing
p.process_event(end_pause());
BOOST_CHECK_MESSAGE(p.current_state()[0] == 3,"Playing should be active"); //Playing
BOOST_CHECK_MESSAGE(p.get_state<player_::Paused&>().exit_counter == 1,"Paused exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::Playing&>().entry_counter == 2,"Playing entry not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<typename player_::Paused&>().exit_counter == 1,"Paused exit not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<typename player_::Playing&>().entry_counter == 2,"Playing entry not called correctly");
p.process_event(pause());
BOOST_CHECK_MESSAGE(p.current_state()[0] == 4,"Paused should be active"); //Paused
BOOST_CHECK_MESSAGE(p.get_state<player_::Playing&>().exit_counter == 2,"Playing exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::Paused&>().entry_counter == 2,"Paused entry not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<typename player_::Playing&>().exit_counter == 2,"Playing exit not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<typename player_::Paused&>().entry_counter == 2,"Paused entry not called correctly");
p.process_event(stop());
BOOST_CHECK_MESSAGE(p.current_state()[0] == 0,"Stopped should be active"); //Stopped
BOOST_CHECK_MESSAGE(p.get_state<player_::Paused&>().exit_counter == 2,"Paused exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::Stopped&>().entry_counter == 2,"Stopped entry not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<typename player_::Paused&>().exit_counter == 2,"Paused exit not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<typename player_::Stopped&>().entry_counter == 2,"Stopped entry not called correctly");
//flags
BOOST_CHECK_MESSAGE(p.is_flag_active<PlayingPaused>() == false,"PlayingPaused should not be active");
BOOST_CHECK_MESSAGE(p.is_flag_active<CDLoaded>() == true,"CDLoaded should be active");
//BOOST_CHECK_MESSAGE(p.is_flag_active<CDLoaded,player::Flag_AND>() == false,"CDLoaded with AND should not be active");
BOOST_CHECK_MESSAGE(p.template is_flag_active<PlayingPaused>() == false,"PlayingPaused should not be active");
BOOST_CHECK_MESSAGE(p.template is_flag_active<CDLoaded>() == true,"CDLoaded should be active");
//BOOST_CHECK_MESSAGE(p.template is_flag_active<CDLoaded,player::Flag_AND>() == false,"CDLoaded with AND should not be active");
p.process_event(stop());
BOOST_CHECK_MESSAGE(p.current_state()[0] == 0,"Stopped should be active"); //Stopped
BOOST_CHECK_MESSAGE(p.get_state<player_::Stopped&>().exit_counter == 2,"Stopped exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::Stopped&>().entry_counter == 3,"Stopped entry not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<typename player_::Stopped&>().exit_counter == 2,"Stopped exit not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<typename player_::Stopped&>().entry_counter == 3,"Stopped entry not called correctly");
//test interrupt
BOOST_CHECK_MESSAGE(p.current_state()[1] == 5,"AllOk should be active"); //AllOk
p.process_event(error_found());
BOOST_CHECK_MESSAGE(p.current_state()[1] == 6,"ErrorMode should be active"); //ErrorMode
BOOST_CHECK_MESSAGE(p.get_state<player_::AllOk&>().exit_counter == 1,"AllOk exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::ErrorMode&>().entry_counter == 1,"ErrorMode entry not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<typename player_::AllOk&>().exit_counter == 1,"AllOk exit not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<typename player_::ErrorMode&>().entry_counter == 1,"ErrorMode entry not called correctly");
// try generating more events
p.process_event(play());
BOOST_CHECK_MESSAGE(p.current_state()[1] == 6,"ErrorMode should be active"); //ErrorMode
BOOST_CHECK_MESSAGE(p.get_state<player_::AllOk&>().exit_counter == 1,"AllOk exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::ErrorMode&>().entry_counter == 1,"ErrorMode entry not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<typename player_::AllOk&>().exit_counter == 1,"AllOk exit not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<typename player_::ErrorMode&>().entry_counter == 1,"ErrorMode entry not called correctly");
BOOST_CHECK_MESSAGE(p.current_state()[0] == 0,"Stopped should be active"); //Stopped
BOOST_CHECK_MESSAGE(p.get_state<player_::Stopped&>().exit_counter == 2,"Stopped exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::Stopped&>().entry_counter == 3,"Stopped entry not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<typename player_::Stopped&>().exit_counter == 2,"Stopped exit not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<typename player_::Stopped&>().entry_counter == 3,"Stopped entry not called correctly");
p.process_event(end_error());
BOOST_CHECK_MESSAGE(p.current_state()[1] == 5,"AllOk should be active"); //AllOk
BOOST_CHECK_MESSAGE(p.get_state<player_::ErrorMode&>().exit_counter == 1,"ErrorMode exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::AllOk&>().entry_counter == 2,"AllOk entry not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<typename player_::ErrorMode&>().exit_counter == 1,"ErrorMode exit not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<typename player_::AllOk&>().entry_counter == 2,"AllOk entry not called correctly");
p.process_event(play());
BOOST_CHECK_MESSAGE(p.current_state()[0] == 3,"Playing should be active"); //Playing
BOOST_CHECK_MESSAGE(p.get_state<player_::Stopped&>().exit_counter == 3,"Stopped exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::Playing&>().entry_counter == 3,"Playing entry not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<typename player_::Stopped&>().exit_counter == 3,"Stopped exit not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<typename player_::Playing&>().entry_counter == 3,"Playing entry not called correctly");
//test terminate
BOOST_CHECK_MESSAGE(p.current_state()[1] == 5,"AllOk should be active"); //AllOk
p.process_event(do_terminate());
BOOST_CHECK_MESSAGE(p.current_state()[1] == 7,"ErrorTerminate should be active"); //ErrorTerminate
BOOST_CHECK_MESSAGE(p.get_state<player_::AllOk&>().exit_counter == 2,"AllOk exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::ErrorTerminate&>().entry_counter == 1,"ErrorTerminate entry not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<typename player_::AllOk&>().exit_counter == 2,"AllOk exit not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<typename player_::ErrorTerminate&>().entry_counter == 1,"ErrorTerminate entry not called correctly");
// try generating more events
p.process_event(stop());
BOOST_CHECK_MESSAGE(p.current_state()[1] == 7,"ErrorTerminate should be active"); //ErrorTerminate
BOOST_CHECK_MESSAGE(p.get_state<player_::ErrorTerminate&>().exit_counter == 0,"ErrorTerminate exit not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<typename player_::ErrorTerminate&>().exit_counter == 0,"ErrorTerminate exit not called correctly");
BOOST_CHECK_MESSAGE(p.current_state()[0] == 3,"Playing should be active"); //Playing
BOOST_CHECK_MESSAGE(p.get_state<player_::Playing&>().exit_counter == 2,"Playing exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::Stopped&>().entry_counter == 3,"Stopped entry not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<typename player_::Playing&>().exit_counter == 2,"Playing exit not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<typename player_::Stopped&>().entry_counter == 3,"Stopped entry not called correctly");
p.process_event(end_error());
BOOST_CHECK_MESSAGE(p.current_state()[1] == 7,"ErrorTerminate should be active"); //ErrorTerminate
BOOST_CHECK_MESSAGE(p.current_state()[0] == 3,"Playing should be active"); //Playing
BOOST_CHECK_MESSAGE(p.get_state<player_::Playing&>().exit_counter == 2,"Playing exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::Stopped&>().entry_counter == 3,"Stopped entry not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<typename player_::Playing&>().exit_counter == 2,"Playing exit not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<typename player_::Stopped&>().entry_counter == 3,"Stopped entry not called correctly");
p.process_event(stop());
BOOST_CHECK_MESSAGE(p.current_state()[1] == 7,"ErrorTerminate should be active"); //ErrorTerminate
BOOST_CHECK_MESSAGE(p.current_state()[0] == 3,"Playing should be active"); //Playing
BOOST_CHECK_MESSAGE(p.get_state<player_::Playing&>().exit_counter == 2,"Playing exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::Stopped&>().entry_counter == 3,"Stopped entry not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<typename player_::Playing&>().exit_counter == 2,"Playing exit not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<typename player_::Stopped&>().entry_counter == 3,"Stopped entry not called correctly");
}
}
using back0 = hierarchical_state_machine<boost::msm::back::state_machine, boost::msm::back::favor_compile_time>::player;
using back1 = hierarchical_state_machine<boost::msm::back::state_machine, boost::msm::back::favor_compile_time>::player_::Playing;
BOOST_MSM_BACK_GENERATE_PROCESS_EVENT(back0);
BOOST_MSM_BACK_GENERATE_PROCESS_EVENT(back1);
+105 -92
View File
@@ -9,12 +9,12 @@
// http://www.boost.org/LICENSE_1_0.txt)
// back-end
#include <boost/msm/back/state_machine.hpp>
#include "BackCommon.hpp"
//front-end
#include <boost/msm/front/state_machine_def.hpp>
#include <boost/msm/front/functor_row.hpp>
#ifndef BOOST_MSM_NONSTANDALONE_TEST
#define BOOST_TEST_MODULE MyTest
#define BOOST_TEST_MODULE orthogonal_deferred3_test
#endif
#include <boost/test/unit_test.hpp>
@@ -51,9 +51,14 @@ namespace
std::string name;
};
template<template <typename...> class Back, typename Policy = void>
struct hierarchical_state_machine
{
// front-end: define the FSM structure
struct player_ : public msm::front::state_machine_def<player_>
{
BOOST_MSM_TEST_DEFINE_DEPENDENT_TEMPLATES(player_);
// we want deferred events and no state requires deferred events (only the fsm in the
// transition table), so the fsm does.
typedef int activate_deferred_events;
@@ -108,6 +113,8 @@ namespace
// by another team in another module. For simplicity I just declare it inside player
struct Playing_ : public msm::front::state_machine_def<Playing_>
{
BOOST_MSM_TEST_DEFINE_DEPENDENT_TEMPLATES(Playing_);
// when playing, the CD is loaded and we are in either pause or playing (duh)
typedef mpl::vector2<PlayingPaused,CDLoaded> flag_list;
@@ -182,7 +189,7 @@ namespace
}
};
// back-end
typedef msm::back::state_machine<Playing_> Playing;
typedef Back<Playing_, Policy> Playing;
// state not defining any entry or exit
struct Paused : public msm::front::state<>
@@ -307,203 +314,209 @@ namespace
template <class Event,class FSM>
void on_entry(Event const&,FSM& fsm)
{
fsm.template get_state<player_::Stopped&>().entry_counter=0;
fsm.template get_state<player_::Stopped&>().exit_counter=0;
fsm.template get_state<player_::Open&>().entry_counter=0;
fsm.template get_state<player_::Open&>().exit_counter=0;
fsm.template get_state<player_::Empty&>().entry_counter=0;
fsm.template get_state<player_::Empty&>().exit_counter=0;
fsm.template get_state<player_::Playing&>().entry_counter=0;
fsm.template get_state<player_::Playing&>().exit_counter=0;
fsm.template get_state<player_::Playing&>().template get_state<player_::Playing::Song1&>().entry_counter=0;
fsm.template get_state<player_::Playing&>().template get_state<player_::Playing::Song1&>().exit_counter=0;
fsm.template get_state<player_::Playing&>().template get_state<player_::Playing::Song2&>().entry_counter=0;
fsm.template get_state<player_::Playing&>().template get_state<player_::Playing::Song2&>().exit_counter=0;
fsm.template get_state<player_::Playing&>().template get_state<player_::Playing::Song3&>().entry_counter=0;
fsm.template get_state<player_::Playing&>().template get_state<player_::Playing::Song3&>().exit_counter=0;
fsm.template get_state<player_::Paused&>().entry_counter=0;
fsm.template get_state<player_::Paused&>().exit_counter=0;
fsm.template get_state<player_::AllOk&>().entry_counter=0;
fsm.template get_state<player_::AllOk&>().exit_counter=0;
fsm.template get_state<player_::ErrorMode&>().entry_counter=0;
fsm.template get_state<player_::ErrorMode&>().exit_counter=0;
fsm.template get_state<player_::ErrorTerminate&>().entry_counter=0;
fsm.template get_state<player_::ErrorTerminate&>().exit_counter=0;
fsm.template get_state<typename player_::Stopped&>().entry_counter=0;
fsm.template get_state<typename player_::Stopped&>().exit_counter=0;
fsm.template get_state<typename player_::Open&>().entry_counter=0;
fsm.template get_state<typename player_::Open&>().exit_counter=0;
fsm.template get_state<typename player_::Empty&>().entry_counter=0;
fsm.template get_state<typename player_::Empty&>().exit_counter=0;
fsm.template get_state<typename player_::Playing&>().entry_counter=0;
fsm.template get_state<typename player_::Playing&>().exit_counter=0;
fsm.template get_state<typename player_::Playing&>().template get_state<typename player_::Playing::Song1&>().entry_counter=0;
fsm.template get_state<typename player_::Playing&>().template get_state<typename player_::Playing::Song1&>().exit_counter=0;
fsm.template get_state<typename player_::Playing&>().template get_state<typename player_::Playing::Song2&>().entry_counter=0;
fsm.template get_state<typename player_::Playing&>().template get_state<typename player_::Playing::Song2&>().exit_counter=0;
fsm.template get_state<typename player_::Playing&>().template get_state<typename player_::Playing::Song3&>().entry_counter=0;
fsm.template get_state<typename player_::Playing&>().template get_state<typename player_::Playing::Song3&>().exit_counter=0;
fsm.template get_state<typename player_::Paused&>().entry_counter=0;
fsm.template get_state<typename player_::Paused&>().exit_counter=0;
fsm.template get_state<typename player_::AllOk&>().entry_counter=0;
fsm.template get_state<typename player_::AllOk&>().exit_counter=0;
fsm.template get_state<typename player_::ErrorMode&>().entry_counter=0;
fsm.template get_state<typename player_::ErrorMode&>().exit_counter=0;
fsm.template get_state<typename player_::ErrorTerminate&>().entry_counter=0;
fsm.template get_state<typename player_::ErrorTerminate&>().exit_counter=0;
}
};
typedef Back<player_, Policy> player;
};
// Pick a back-end
typedef msm::back::state_machine<player_> player;
typedef boost::mpl::vector<
hierarchical_state_machine<boost::msm::back::state_machine>,
hierarchical_state_machine<boost::msm::back11::state_machine>
> test_machines;
//static char const* const state_names[] = { "Stopped", "Open", "Empty", "Playing", "Paused","AllOk","ErrorMode" };
BOOST_AUTO_TEST_CASE( orthogonal_deferred3_test )
BOOST_AUTO_TEST_CASE_TEMPLATE( orthogonal_deferred3_test, test_machine, test_machines )
{
player p;
typename test_machine::player p;
typedef typename test_machine::player_ player_;
// needed to start the highest-level SM. This will call on_entry and mark the start of the SM
p.start();
// test deferred event
// deferred in Empty and Open, will be handled only after event cd_detected
p.process_event(play());
BOOST_CHECK_MESSAGE(p.current_state()[0] == 2,"Empty should be active"); //Empty
BOOST_CHECK_MESSAGE(p.get_state<player_::Open&>().exit_counter == 0,"Open exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::Playing&>().entry_counter == 0,"Playing entry not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::Empty&>().entry_counter == 1,"Empty entry not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<typename player_::Open&>().exit_counter == 0,"Open exit not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<typename player_::Playing&>().entry_counter == 0,"Playing entry not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<typename player_::Empty&>().entry_counter == 1,"Empty entry not called correctly");
//flags
BOOST_CHECK_MESSAGE(p.is_flag_active<CDLoaded>() == false,"CDLoaded should not be active");
BOOST_CHECK_MESSAGE(p.template is_flag_active<CDLoaded>() == false,"CDLoaded should not be active");
p.process_event(open_close());
BOOST_CHECK_MESSAGE(p.current_state()[0] == 1,"Open should be active"); //Open
BOOST_CHECK_MESSAGE(p.get_state<player_::Empty&>().exit_counter == 1,"Empty exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::Open&>().entry_counter == 1,"Open entry not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<typename player_::Empty&>().exit_counter == 1,"Empty exit not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<typename player_::Open&>().entry_counter == 1,"Open entry not called correctly");
p.process_event(open_close());
BOOST_CHECK_MESSAGE(p.current_state()[0] == 2,"Empty should be active"); //Empty
BOOST_CHECK_MESSAGE(p.get_state<player_::Open&>().exit_counter == 1,"Open exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::Empty&>().entry_counter == 2,"Empty entry not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<typename player_::Open&>().exit_counter == 1,"Open exit not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<typename player_::Empty&>().entry_counter == 2,"Empty entry not called correctly");
BOOST_CHECK_MESSAGE(p.can_close_drawer_counter == 1,"guard not called correctly");
//deferred event should have been processed
p.process_event(cd_detected("louie, louie"));
BOOST_CHECK_MESSAGE(p.current_state()[0] == 3,"Playing should be active"); //Playing
BOOST_CHECK_MESSAGE(p.get_state<player_::Empty&>().exit_counter == 2,"Empty exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::Stopped&>().entry_counter == 1,"Stopped entry not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::Stopped&>().exit_counter == 1,"Stopped exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::Playing&>().entry_counter == 1,"Playing entry not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<typename player_::Empty&>().exit_counter == 2,"Empty exit not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<typename player_::Stopped&>().entry_counter == 1,"Stopped entry not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<typename player_::Stopped&>().exit_counter == 1,"Stopped exit not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<typename player_::Playing&>().entry_counter == 1,"Playing entry not called correctly");
BOOST_CHECK_MESSAGE(p.start_playback_counter == 1,"action not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::Playing&>().current_state()[0] == 0,"Song1 should be active");
BOOST_CHECK_MESSAGE(p.template get_state<typename player_::Playing&>().current_state()[0] == 0,"Song1 should be active");
BOOST_CHECK_MESSAGE(
p.get_state<player_::Playing&>().get_state<player_::Playing::Song1&>().entry_counter == 1,
p.template get_state<typename player_::Playing&>().template get_state<typename player_::Playing::Song1&>().entry_counter == 1,
"Song1 entry not called correctly");
//flags
BOOST_CHECK_MESSAGE(p.is_flag_active<PlayingPaused>() == true,"PlayingPaused should be active");
BOOST_CHECK_MESSAGE(p.is_flag_active<FirstSongPlaying>() == true,"FirstSongPlaying should be active");
BOOST_CHECK_MESSAGE(p.template is_flag_active<PlayingPaused>() == true,"PlayingPaused should be active");
BOOST_CHECK_MESSAGE(p.template is_flag_active<FirstSongPlaying>() == true,"FirstSongPlaying should be active");
p.process_event(NextSong());
BOOST_CHECK_MESSAGE(p.current_state()[0] == 3,"Playing should be active"); //Playing
BOOST_CHECK_MESSAGE(p.get_state<player_::Playing&>().current_state()[0] == 1,"Song2 should be active");
BOOST_CHECK_MESSAGE(p.template get_state<typename player_::Playing&>().current_state()[0] == 1,"Song2 should be active");
BOOST_CHECK_MESSAGE(
p.get_state<player_::Playing&>().get_state<player_::Playing::Song2&>().entry_counter == 1,
p.template get_state<typename player_::Playing&>().template get_state<typename player_::Playing::Song2&>().entry_counter == 1,
"Song2 entry not called correctly");
BOOST_CHECK_MESSAGE(
p.get_state<player_::Playing&>().get_state<player_::Playing::Song1&>().exit_counter == 1,
p.template get_state<typename player_::Playing&>().template get_state<typename player_::Playing::Song1&>().exit_counter == 1,
"Song1 exit not called correctly");
BOOST_CHECK_MESSAGE(
p.get_state<player_::Playing&>().start_next_song_counter == 0,
p.template get_state<typename player_::Playing&>().start_next_song_counter == 0,
"submachine action not called correctly");
p.process_event(NextSong());
BOOST_CHECK_MESSAGE(p.current_state()[0] == 3,"Playing should be active"); //Playing
BOOST_CHECK_MESSAGE(p.get_state<player_::Playing&>().current_state()[0] == 2,"Song3 should be active");
BOOST_CHECK_MESSAGE(p.template get_state<typename player_::Playing&>().current_state()[0] == 2,"Song3 should be active");
BOOST_CHECK_MESSAGE(
p.get_state<player_::Playing&>().get_state<player_::Playing::Song3&>().entry_counter == 1,
p.template get_state<typename player_::Playing&>().template get_state<typename player_::Playing::Song3&>().entry_counter == 1,
"Song3 entry not called correctly");
BOOST_CHECK_MESSAGE(
p.get_state<player_::Playing&>().get_state<player_::Playing::Song2&>().exit_counter == 1,
p.template get_state<typename player_::Playing&>().template get_state<typename player_::Playing::Song2&>().exit_counter == 1,
"Song2 exit not called correctly");
BOOST_CHECK_MESSAGE(
p.get_state<player_::Playing&>().start_next_song_counter == 1,
p.template get_state<typename player_::Playing&>().start_next_song_counter == 1,
"submachine action not called correctly");
p.process_event(PreviousSong());
BOOST_CHECK_MESSAGE(p.current_state()[0] == 3,"Playing should be active"); //Playing
BOOST_CHECK_MESSAGE(p.get_state<player_::Playing&>().current_state()[0] == 1,"Song2 should be active");
BOOST_CHECK_MESSAGE(p.template get_state<typename player_::Playing&>().current_state()[0] == 1,"Song2 should be active");
BOOST_CHECK_MESSAGE(
p.get_state<player_::Playing&>().get_state<player_::Playing::Song2&>().entry_counter == 2,
p.template get_state<typename player_::Playing&>().template get_state<typename player_::Playing::Song2&>().entry_counter == 2,
"Song2 entry not called correctly");
BOOST_CHECK_MESSAGE(
p.get_state<player_::Playing&>().get_state<player_::Playing::Song3&>().exit_counter == 1,
p.template get_state<typename player_::Playing&>().template get_state<typename player_::Playing::Song3&>().exit_counter == 1,
"Song3 exit not called correctly");
BOOST_CHECK_MESSAGE(
p.get_state<player_::Playing&>().start_prev_song_guard_counter == 1,
p.template get_state<typename player_::Playing&>().start_prev_song_guard_counter == 1,
"submachine guard not called correctly");
//flags
BOOST_CHECK_MESSAGE(p.is_flag_active<PlayingPaused>() == true,"PlayingPaused should be active");
BOOST_CHECK_MESSAGE(p.is_flag_active<FirstSongPlaying>() == false,"FirstSongPlaying should not be active");
BOOST_CHECK_MESSAGE(p.template is_flag_active<PlayingPaused>() == true,"PlayingPaused should be active");
BOOST_CHECK_MESSAGE(p.template is_flag_active<FirstSongPlaying>() == false,"FirstSongPlaying should not be active");
p.process_event(pause());
BOOST_CHECK_MESSAGE(p.current_state()[0] == 4,"Paused should be active"); //Paused
BOOST_CHECK_MESSAGE(p.get_state<player_::Playing&>().exit_counter == 1,"Playing exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::Paused&>().entry_counter == 1,"Paused entry not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<typename player_::Playing&>().exit_counter == 1,"Playing exit not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<typename player_::Paused&>().entry_counter == 1,"Paused entry not called correctly");
//flags
BOOST_CHECK_MESSAGE(p.is_flag_active<PlayingPaused>() == true,"PlayingPaused should be active");
BOOST_CHECK_MESSAGE(p.template is_flag_active<PlayingPaused>() == true,"PlayingPaused should be active");
// go back to Playing
p.process_event(end_pause());
BOOST_CHECK_MESSAGE(p.current_state()[0] == 3,"Playing should be active"); //Playing
BOOST_CHECK_MESSAGE(p.get_state<player_::Paused&>().exit_counter == 1,"Paused exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::Playing&>().entry_counter == 2,"Playing entry not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<typename player_::Paused&>().exit_counter == 1,"Paused exit not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<typename player_::Playing&>().entry_counter == 2,"Playing entry not called correctly");
p.process_event(pause());
BOOST_CHECK_MESSAGE(p.current_state()[0] == 4,"Paused should be active"); //Paused
BOOST_CHECK_MESSAGE(p.get_state<player_::Playing&>().exit_counter == 2,"Playing exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::Paused&>().entry_counter == 2,"Paused entry not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<typename player_::Playing&>().exit_counter == 2,"Playing exit not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<typename player_::Paused&>().entry_counter == 2,"Paused entry not called correctly");
p.process_event(stop());
BOOST_CHECK_MESSAGE(p.current_state()[0] == 0,"Stopped should be active"); //Stopped
BOOST_CHECK_MESSAGE(p.get_state<player_::Paused&>().exit_counter == 2,"Paused exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::Stopped&>().entry_counter == 2,"Stopped entry not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<typename player_::Paused&>().exit_counter == 2,"Paused exit not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<typename player_::Stopped&>().entry_counter == 2,"Stopped entry not called correctly");
//flags
BOOST_CHECK_MESSAGE(p.is_flag_active<PlayingPaused>() == false,"PlayingPaused should not be active");
BOOST_CHECK_MESSAGE(p.is_flag_active<CDLoaded>() == true,"CDLoaded should be active");
//BOOST_CHECK_MESSAGE(p.is_flag_active<CDLoaded,player::Flag_AND>() == false,"CDLoaded with AND should not be active");
BOOST_CHECK_MESSAGE(p.template is_flag_active<PlayingPaused>() == false,"PlayingPaused should not be active");
BOOST_CHECK_MESSAGE(p.template is_flag_active<CDLoaded>() == true,"CDLoaded should be active");
//BOOST_CHECK_MESSAGE(p.template is_flag_active<CDLoaded,player::Flag_AND>() == false,"CDLoaded with AND should not be active");
p.process_event(stop());
BOOST_CHECK_MESSAGE(p.current_state()[0] == 0,"Stopped should be active"); //Stopped
BOOST_CHECK_MESSAGE(p.get_state<player_::Stopped&>().exit_counter == 2,"Stopped exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::Stopped&>().entry_counter == 3,"Stopped entry not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<typename player_::Stopped&>().exit_counter == 2,"Stopped exit not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<typename player_::Stopped&>().entry_counter == 3,"Stopped entry not called correctly");
//test interrupt
BOOST_CHECK_MESSAGE(p.current_state()[1] == 5,"AllOk should be active"); //AllOk
p.process_event(error_found());
BOOST_CHECK_MESSAGE(p.current_state()[1] == 6,"ErrorMode should be active"); //ErrorMode
BOOST_CHECK_MESSAGE(p.get_state<player_::AllOk&>().exit_counter == 1,"AllOk exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::ErrorMode&>().entry_counter == 1,"ErrorMode entry not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<typename player_::AllOk&>().exit_counter == 1,"AllOk exit not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<typename player_::ErrorMode&>().entry_counter == 1,"ErrorMode entry not called correctly");
// try generating more events
p.process_event(play());
BOOST_CHECK_MESSAGE(p.current_state()[1] == 6,"ErrorMode should be active"); //ErrorMode
BOOST_CHECK_MESSAGE(p.get_state<player_::AllOk&>().exit_counter == 1,"AllOk exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::ErrorMode&>().entry_counter == 1,"ErrorMode entry not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<typename player_::AllOk&>().exit_counter == 1,"AllOk exit not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<typename player_::ErrorMode&>().entry_counter == 1,"ErrorMode entry not called correctly");
BOOST_CHECK_MESSAGE(p.current_state()[0] == 0,"Stopped should be active"); //Stopped
BOOST_CHECK_MESSAGE(p.get_state<player_::Stopped&>().exit_counter == 2,"Stopped exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::Stopped&>().entry_counter == 3,"Stopped entry not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<typename player_::Stopped&>().exit_counter == 2,"Stopped exit not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<typename player_::Stopped&>().entry_counter == 3,"Stopped entry not called correctly");
p.process_event(end_error());
BOOST_CHECK_MESSAGE(p.current_state()[1] == 5,"AllOk should be active"); //AllOk
BOOST_CHECK_MESSAGE(p.get_state<player_::ErrorMode&>().exit_counter == 1,"ErrorMode exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::AllOk&>().entry_counter == 2,"AllOk entry not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<typename player_::ErrorMode&>().exit_counter == 1,"ErrorMode exit not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<typename player_::AllOk&>().entry_counter == 2,"AllOk entry not called correctly");
p.process_event(play());
BOOST_CHECK_MESSAGE(p.current_state()[0] == 3,"Playing should be active"); //Playing
BOOST_CHECK_MESSAGE(p.get_state<player_::Stopped&>().exit_counter == 3,"Stopped exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::Playing&>().entry_counter == 3,"Playing entry not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<typename player_::Stopped&>().exit_counter == 3,"Stopped exit not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<typename player_::Playing&>().entry_counter == 3,"Playing entry not called correctly");
//test terminate
BOOST_CHECK_MESSAGE(p.current_state()[1] == 5,"AllOk should be active"); //AllOk
p.process_event(do_terminate());
BOOST_CHECK_MESSAGE(p.current_state()[1] == 7,"ErrorTerminate should be active"); //ErrorTerminate
BOOST_CHECK_MESSAGE(p.get_state<player_::AllOk&>().exit_counter == 2,"AllOk exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::ErrorTerminate&>().entry_counter == 1,"ErrorTerminate entry not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<typename player_::AllOk&>().exit_counter == 2,"AllOk exit not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<typename player_::ErrorTerminate&>().entry_counter == 1,"ErrorTerminate entry not called correctly");
// try generating more events
p.process_event(stop());
BOOST_CHECK_MESSAGE(p.current_state()[1] == 7,"ErrorTerminate should be active"); //ErrorTerminate
BOOST_CHECK_MESSAGE(p.get_state<player_::ErrorTerminate&>().exit_counter == 0,"ErrorTerminate exit not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<typename player_::ErrorTerminate&>().exit_counter == 0,"ErrorTerminate exit not called correctly");
BOOST_CHECK_MESSAGE(p.current_state()[0] == 3,"Playing should be active"); //Playing
BOOST_CHECK_MESSAGE(p.get_state<player_::Playing&>().exit_counter == 2,"Playing exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::Stopped&>().entry_counter == 3,"Stopped entry not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<typename player_::Playing&>().exit_counter == 2,"Playing exit not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<typename player_::Stopped&>().entry_counter == 3,"Stopped entry not called correctly");
p.process_event(end_error());
BOOST_CHECK_MESSAGE(p.current_state()[1] == 7,"ErrorTerminate should be active"); //ErrorTerminate
BOOST_CHECK_MESSAGE(p.current_state()[0] == 3,"Playing should be active"); //Playing
BOOST_CHECK_MESSAGE(p.get_state<player_::Playing&>().exit_counter == 2,"Playing exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::Stopped&>().entry_counter == 3,"Stopped entry not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<typename player_::Playing&>().exit_counter == 2,"Playing exit not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<typename player_::Stopped&>().entry_counter == 3,"Stopped entry not called correctly");
p.process_event(stop());
BOOST_CHECK_MESSAGE(p.current_state()[1] == 7,"ErrorTerminate should be active"); //ErrorTerminate
BOOST_CHECK_MESSAGE(p.current_state()[0] == 3,"Playing should be active"); //Playing
BOOST_CHECK_MESSAGE(p.get_state<player_::Playing&>().exit_counter == 2,"Playing exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::Stopped&>().entry_counter == 3,"Stopped entry not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<typename player_::Playing&>().exit_counter == 2,"Playing exit not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<typename player_::Stopped&>().entry_counter == 3,"Stopped entry not called correctly");
}
}
+93 -74
View File
@@ -9,12 +9,12 @@
// http://www.boost.org/LICENSE_1_0.txt)
// back-end
#include <boost/msm/back/state_machine.hpp>
#include "BackCommon.hpp"
//front-end
#include <boost/msm/front/state_machine_def.hpp>
#include <boost/msm/front/euml/euml.hpp>
#ifndef BOOST_MSM_NONSTANDALONE_TEST
#define BOOST_TEST_MODULE MyOrthogonalDeferredEumlTest
#define BOOST_TEST_MODULE orthogonal_deferred_euml_test
#endif
#include <boost/test/unit_test.hpp>
@@ -65,15 +65,23 @@ namespace
BOOST_MSM_EUML_INTERRUPT_STATE(( end_error,++state_(entry_counter),++state_(exit_counter),attributes_ << entry_counter << exit_counter),
ErrorMode)
// Playing is now a state machine itself.
// State machine attributes.
BOOST_MSM_EUML_DECLARE_ATTRIBUTE(unsigned int,start_playback_counter)
BOOST_MSM_EUML_DECLARE_ATTRIBUTE(unsigned int,can_close_drawer_counter)
BOOST_MSM_EUML_DECLARE_ATTRIBUTE(unsigned int,report_error_counter)
BOOST_MSM_EUML_DECLARE_ATTRIBUTE(unsigned int,report_end_error_counter)
BOOST_MSM_EUML_DECLARE_ATTRIBUTE(unsigned int,start_next_song_counter)
BOOST_MSM_EUML_DECLARE_ATTRIBUTE(unsigned int,start_prev_song_guard_counter)
// Playing is now a state machine itself.
BOOST_MSM_EUML_STATE(( ++state_(entry_counter),++state_(exit_counter),
attributes_ << entry_counter << exit_counter, configure_<< FirstSongPlaying ),Song1)
BOOST_MSM_EUML_STATE(( ++state_(entry_counter),++state_(exit_counter),attributes_ << entry_counter << exit_counter),Song2)
BOOST_MSM_EUML_STATE(( ++state_(entry_counter),++state_(exit_counter),attributes_ << entry_counter << exit_counter),Song3)
template<template <typename...> class Back, typename Policy = void>
struct hierarchical_state_machine
{
// Playing has a transition table
BOOST_MSM_EUML_TRANSITION_TABLE((
// +------------------------------------------------------------------------------+
@@ -95,14 +103,10 @@ namespace
),Playing_)
// back-end
typedef msm::back::state_machine<Playing_> Playing_type;
typedef Back<Playing_, Policy> Playing_type;
Playing_type const Playing;
//fsm
BOOST_MSM_EUML_DECLARE_ATTRIBUTE(unsigned int,start_playback_counter)
BOOST_MSM_EUML_DECLARE_ATTRIBUTE(unsigned int,can_close_drawer_counter)
BOOST_MSM_EUML_DECLARE_ATTRIBUTE(unsigned int,report_error_counter)
BOOST_MSM_EUML_DECLARE_ATTRIBUTE(unsigned int,report_end_error_counter)
BOOST_MSM_EUML_ACTION(No_Transition)
{
template <class FSM,class Event>
@@ -146,213 +150,228 @@ namespace
),
player_) //fsm name
typedef Back<player_, Policy> player;
};
// Pick a back-end
typedef msm::back::state_machine<player_> player;
typedef boost::mpl::vector<
hierarchical_state_machine<boost::msm::back::state_machine>,
hierarchical_state_machine<boost::msm::back::state_machine, boost::msm::back::favor_compile_time>
// TODO:
// Investigate reason for test failure in back11.
// hierarchical_state_machine<boost::msm::back11::state_machine>
> test_machines;
//static char const* const state_names[] = { "Stopped", "Paused","Open", "Empty", "Playing" ,"AllOk","ErrorMode","ErrorTerminate" };
BOOST_AUTO_TEST_CASE(MyOrthogonalDeferredEumlTest)
BOOST_AUTO_TEST_CASE_TEMPLATE(orthogonal_deferred_euml_test, test_machine, test_machines)
{
player p;
typename test_machine::player p;
typedef typename test_machine::player_ player_;
typedef typename test_machine::Playing_type Playing_type;
// needed to start the highest-level SM. This will call on_entry and mark the start of the SM
p.start();
// test deferred event
// deferred in Empty and Open, will be handled only after event cd_detected
p.process_event(play);
BOOST_CHECK_MESSAGE(p.current_state()[0] == 3,"Empty should be active"); //Empty
BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(Open)&>().get_attribute(exit_counter) == 0,
BOOST_CHECK_MESSAGE(p.template get_state<BOOST_MSM_EUML_STATE_NAME(Open)&>().get_attribute(exit_counter) == 0,
"Open exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<Playing_type&>().get_attribute(entry_counter) == 0,"Playing entry not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(Empty)&>().get_attribute(entry_counter) == 1,
BOOST_CHECK_MESSAGE(p.template get_state<Playing_type&>().get_attribute(entry_counter) == 0,"Playing entry not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<BOOST_MSM_EUML_STATE_NAME(Empty)&>().get_attribute(entry_counter) == 1,
"Empty entry not called correctly");
//flags
BOOST_CHECK_MESSAGE(p.is_flag_active<BOOST_MSM_EUML_FLAG_NAME(CDLoaded)>() == false,"CDLoaded should not be active");
BOOST_CHECK_MESSAGE(p.template is_flag_active<BOOST_MSM_EUML_FLAG_NAME(CDLoaded)>() == false,"CDLoaded should not be active");
p.process_event(open_close);
BOOST_CHECK_MESSAGE(p.current_state()[0] == 2,"Open should be active"); //Open
BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(Empty)&>().get_attribute(exit_counter) == 1,
BOOST_CHECK_MESSAGE(p.template get_state<BOOST_MSM_EUML_STATE_NAME(Empty)&>().get_attribute(exit_counter) == 1,
"Empty exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(Open)&>().get_attribute(entry_counter) == 1,
BOOST_CHECK_MESSAGE(p.template get_state<BOOST_MSM_EUML_STATE_NAME(Open)&>().get_attribute(entry_counter) == 1,
"Open entry not called correctly");
p.process_event(open_close);
BOOST_CHECK_MESSAGE(p.current_state()[0] == 3,"Empty should be active"); //Empty
BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(Open)&>().get_attribute(exit_counter) == 1,
BOOST_CHECK_MESSAGE(p.template get_state<BOOST_MSM_EUML_STATE_NAME(Open)&>().get_attribute(exit_counter) == 1,
"Open exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(Empty)&>().get_attribute(entry_counter) == 2,
BOOST_CHECK_MESSAGE(p.template get_state<BOOST_MSM_EUML_STATE_NAME(Empty)&>().get_attribute(entry_counter) == 2,
"Empty entry not called correctly");
BOOST_CHECK_MESSAGE(p.get_attribute(can_close_drawer_counter) == 1,"guard not called correctly");
//deferred event should have been processed
p.process_event(cd_detected("louie, louie"));
BOOST_CHECK_MESSAGE(p.current_state()[0] == 4,"Playing should be active"); //Playing
BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(Empty)&>().get_attribute(exit_counter) == 2,
BOOST_CHECK_MESSAGE(p.template get_state<BOOST_MSM_EUML_STATE_NAME(Empty)&>().get_attribute(exit_counter) == 2,
"Empty exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(Stopped)&>().get_attribute(entry_counter) == 1,
BOOST_CHECK_MESSAGE(p.template get_state<BOOST_MSM_EUML_STATE_NAME(Stopped)&>().get_attribute(entry_counter) == 1,
"Stopped entry not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(Stopped)&>().get_attribute(exit_counter) == 1,
BOOST_CHECK_MESSAGE(p.template get_state<BOOST_MSM_EUML_STATE_NAME(Stopped)&>().get_attribute(exit_counter) == 1,
"Stopped exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<Playing_type&>().get_attribute(entry_counter) == 1,"Playing entry not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<Playing_type&>().get_attribute(entry_counter) == 1,"Playing entry not called correctly");
BOOST_CHECK_MESSAGE(p.get_attribute(start_playback_counter) == 1,"action not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<Playing_type&>().current_state()[0] == 0,"Song1 should be active");
BOOST_CHECK_MESSAGE(p.template get_state<Playing_type&>().current_state()[0] == 0,"Song1 should be active");
BOOST_CHECK_MESSAGE(
p.get_state<Playing_type&>().get_state<BOOST_MSM_EUML_STATE_NAME(Song1)&>().get_attribute(entry_counter) == 1,
p.template get_state<Playing_type&>().template get_state<BOOST_MSM_EUML_STATE_NAME(Song1)&>().get_attribute(entry_counter) == 1,
"Song1 entry not called correctly");
//flags
BOOST_CHECK_MESSAGE(p.is_flag_active<BOOST_MSM_EUML_FLAG_NAME(PlayingPaused)>() == true,"PlayingPaused should be active");
BOOST_CHECK_MESSAGE(p.is_flag_active<BOOST_MSM_EUML_FLAG_NAME(FirstSongPlaying)>() == true,"FirstSongPlaying should be active");
BOOST_CHECK_MESSAGE(p.template is_flag_active<BOOST_MSM_EUML_FLAG_NAME(PlayingPaused)>() == true,"PlayingPaused should be active");
BOOST_CHECK_MESSAGE(p.template is_flag_active<BOOST_MSM_EUML_FLAG_NAME(FirstSongPlaying)>() == true,"FirstSongPlaying should be active");
p.process_event(next_song);
BOOST_CHECK_MESSAGE(p.current_state()[0] == 4,"Playing should be active"); //Playing
BOOST_CHECK_MESSAGE(p.get_state<Playing_type&>().current_state()[0] == 1,"Song2 should be active");
BOOST_CHECK_MESSAGE(p.template get_state<Playing_type&>().current_state()[0] == 1,"Song2 should be active");
BOOST_CHECK_MESSAGE(
p.get_state<Playing_type&>().get_state<BOOST_MSM_EUML_STATE_NAME(Song2)&>().get_attribute(entry_counter) == 1,
p.template get_state<Playing_type&>().template get_state<BOOST_MSM_EUML_STATE_NAME(Song2)&>().get_attribute(entry_counter) == 1,
"Song2 entry not called correctly");
BOOST_CHECK_MESSAGE(
p.get_state<Playing_type&>().get_state<BOOST_MSM_EUML_STATE_NAME(Song1)&>().get_attribute(exit_counter) == 1,
p.template get_state<Playing_type&>().template get_state<BOOST_MSM_EUML_STATE_NAME(Song1)&>().get_attribute(exit_counter) == 1,
"Song1 exit not called correctly");
BOOST_CHECK_MESSAGE(
p.get_state<Playing_type&>().get_attribute(start_next_song_counter) == 0,
p.template get_state<Playing_type&>().get_attribute(start_next_song_counter) == 0,
"submachine action not called correctly");
p.process_event(next_song);
BOOST_CHECK_MESSAGE(p.current_state()[0] == 4,"Playing should be active"); //Playing
BOOST_CHECK_MESSAGE(p.get_state<Playing_type&>().current_state()[0] == 2,"Song3 should be active");
BOOST_CHECK_MESSAGE(p.template get_state<Playing_type&>().current_state()[0] == 2,"Song3 should be active");
BOOST_CHECK_MESSAGE(
p.get_state<Playing_type&>().get_state<BOOST_MSM_EUML_STATE_NAME(Song3)&>().get_attribute(entry_counter) == 1,
p.template get_state<Playing_type&>().template get_state<BOOST_MSM_EUML_STATE_NAME(Song3)&>().get_attribute(entry_counter) == 1,
"Song3 entry not called correctly");
BOOST_CHECK_MESSAGE(
p.get_state<Playing_type&>().get_state<BOOST_MSM_EUML_STATE_NAME(Song2)&>().get_attribute(exit_counter) == 1,
p.template get_state<Playing_type&>().template get_state<BOOST_MSM_EUML_STATE_NAME(Song2)&>().get_attribute(exit_counter) == 1,
"Song2 exit not called correctly");
BOOST_CHECK_MESSAGE(
p.get_state<Playing_type&>().get_attribute(start_next_song_counter) == 1,
p.template get_state<Playing_type&>().get_attribute(start_next_song_counter) == 1,
"submachine action not called correctly");
p.process_event(previous_song);
BOOST_CHECK_MESSAGE(p.current_state()[0] == 4,"Playing should be active"); //Playing
BOOST_CHECK_MESSAGE(p.get_state<Playing_type&>().current_state()[0] == 1,"Song2 should be active");
BOOST_CHECK_MESSAGE(p.template get_state<Playing_type&>().current_state()[0] == 1,"Song2 should be active");
BOOST_CHECK_MESSAGE(
p.get_state<Playing_type&>().get_state<BOOST_MSM_EUML_STATE_NAME(Song2)&>().get_attribute(entry_counter) == 2,
p.template get_state<Playing_type&>().template get_state<BOOST_MSM_EUML_STATE_NAME(Song2)&>().get_attribute(entry_counter) == 2,
"Song2 entry not called correctly");
BOOST_CHECK_MESSAGE(
p.get_state<Playing_type&>().get_state<BOOST_MSM_EUML_STATE_NAME(Song3)&>().get_attribute(exit_counter) == 1,
p.template get_state<Playing_type&>().template get_state<BOOST_MSM_EUML_STATE_NAME(Song3)&>().get_attribute(exit_counter) == 1,
"Song3 exit not called correctly");
BOOST_CHECK_MESSAGE(
p.get_state<Playing_type&>().get_attribute(start_prev_song_guard_counter) == 1,
p.template get_state<Playing_type&>().get_attribute(start_prev_song_guard_counter) == 1,
"submachine guard not called correctly");
//flags
BOOST_CHECK_MESSAGE(p.is_flag_active<BOOST_MSM_EUML_FLAG_NAME(PlayingPaused)>() == true,"PlayingPaused should be active");
BOOST_CHECK_MESSAGE(p.is_flag_active<BOOST_MSM_EUML_FLAG_NAME(FirstSongPlaying)>() == false,"FirstSongPlaying should not be active");
BOOST_CHECK_MESSAGE(p.template is_flag_active<BOOST_MSM_EUML_FLAG_NAME(PlayingPaused)>() == true,"PlayingPaused should be active");
BOOST_CHECK_MESSAGE(p.template is_flag_active<BOOST_MSM_EUML_FLAG_NAME(FirstSongPlaying)>() == false,"FirstSongPlaying should not be active");
p.process_event(pause());
BOOST_CHECK_MESSAGE(p.current_state()[0] == 1,"Paused should be active"); //Paused
BOOST_CHECK_MESSAGE(p.get_state<Playing_type&>().get_attribute(exit_counter) == 1,"Playing exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(Paused)&>().get_attribute(entry_counter) == 1,
BOOST_CHECK_MESSAGE(p.template get_state<Playing_type&>().get_attribute(exit_counter) == 1,"Playing exit not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<BOOST_MSM_EUML_STATE_NAME(Paused)&>().get_attribute(entry_counter) == 1,
"Paused entry not called correctly");
//flags
BOOST_CHECK_MESSAGE(p.is_flag_active<BOOST_MSM_EUML_FLAG_NAME(PlayingPaused)>() == true,"PlayingPaused should be active");
BOOST_CHECK_MESSAGE(p.template is_flag_active<BOOST_MSM_EUML_FLAG_NAME(PlayingPaused)>() == true,"PlayingPaused should be active");
// go back to Playing
p.process_event(end_pause);
BOOST_CHECK_MESSAGE(p.current_state()[0] == 4,"Playing should be active"); //Playing
BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(Paused)&>().get_attribute(exit_counter) == 1,
BOOST_CHECK_MESSAGE(p.template get_state<BOOST_MSM_EUML_STATE_NAME(Paused)&>().get_attribute(exit_counter) == 1,
"Paused exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<Playing_type&>().get_attribute(entry_counter) == 2,"Playing entry not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<Playing_type&>().get_attribute(entry_counter) == 2,"Playing entry not called correctly");
p.process_event(pause);
BOOST_CHECK_MESSAGE(p.current_state()[0] == 1,"Paused should be active"); //Paused
BOOST_CHECK_MESSAGE(p.get_state<Playing_type&>().get_attribute(exit_counter) == 2,"Playing exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(Paused)&>().get_attribute(entry_counter) == 2,
BOOST_CHECK_MESSAGE(p.template get_state<Playing_type&>().get_attribute(exit_counter) == 2,"Playing exit not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<BOOST_MSM_EUML_STATE_NAME(Paused)&>().get_attribute(entry_counter) == 2,
"Paused entry not called correctly");
p.process_event(stop);
BOOST_CHECK_MESSAGE(p.current_state()[0] == 0,"Stopped should be active"); //Stopped
BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(Paused)&>().get_attribute(exit_counter) == 2,
BOOST_CHECK_MESSAGE(p.template get_state<BOOST_MSM_EUML_STATE_NAME(Paused)&>().get_attribute(exit_counter) == 2,
"Paused exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(Stopped)&>().get_attribute(entry_counter) == 2,
BOOST_CHECK_MESSAGE(p.template get_state<BOOST_MSM_EUML_STATE_NAME(Stopped)&>().get_attribute(entry_counter) == 2,
"Stopped entry not called correctly");
//flags
BOOST_CHECK_MESSAGE(p.is_flag_active<BOOST_MSM_EUML_FLAG_NAME(PlayingPaused)>() == false,"PlayingPaused should not be active");
BOOST_CHECK_MESSAGE(p.is_flag_active<BOOST_MSM_EUML_FLAG_NAME(CDLoaded)>() == true,"CDLoaded should be active");
//BOOST_CHECK_MESSAGE(p.is_flag_active<BOOST_MSM_EUML_FLAG_NAME(CDLoaded),player::Flag_AND>() == false,"CDLoaded with AND should not be active");
BOOST_CHECK_MESSAGE(p.template is_flag_active<BOOST_MSM_EUML_FLAG_NAME(PlayingPaused)>() == false,"PlayingPaused should not be active");
BOOST_CHECK_MESSAGE(p.template is_flag_active<BOOST_MSM_EUML_FLAG_NAME(CDLoaded)>() == true,"CDLoaded should be active");
//BOOST_CHECK_MESSAGE(p.template is_flag_active<BOOST_MSM_EUML_FLAG_NAME(CDLoaded),player::Flag_AND>() == false,"CDLoaded with AND should not be active");
p.process_event(stop);
BOOST_CHECK_MESSAGE(p.current_state()[0] == 0,"Stopped should be active"); //Stopped
BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(Stopped)&>().get_attribute(exit_counter) == 2,
BOOST_CHECK_MESSAGE(p.template get_state<BOOST_MSM_EUML_STATE_NAME(Stopped)&>().get_attribute(exit_counter) == 2,
"Stopped exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(Stopped)&>().get_attribute(entry_counter) == 3,
BOOST_CHECK_MESSAGE(p.template get_state<BOOST_MSM_EUML_STATE_NAME(Stopped)&>().get_attribute(entry_counter) == 3,
"Stopped entry not called correctly");
//test interrupt
BOOST_CHECK_MESSAGE(p.current_state()[1] == 5,"AllOk should be active"); //AllOk
p.process_event(error_found);
BOOST_CHECK_MESSAGE(p.current_state()[1] == 6,"ErrorMode should be active"); //ErrorMode
BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(AllOk)&>().get_attribute(exit_counter) == 1,
BOOST_CHECK_MESSAGE(p.template get_state<BOOST_MSM_EUML_STATE_NAME(AllOk)&>().get_attribute(exit_counter) == 1,
"AllOk exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(ErrorMode)&>().get_attribute(entry_counter) == 1,
BOOST_CHECK_MESSAGE(p.template get_state<BOOST_MSM_EUML_STATE_NAME(ErrorMode)&>().get_attribute(entry_counter) == 1,
"ErrorMode entry not called correctly");
// try generating more events
p.process_event(play);
BOOST_CHECK_MESSAGE(p.current_state()[1] == 6,"ErrorMode should be active"); //ErrorMode
BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(AllOk)&>().get_attribute(exit_counter) == 1,
BOOST_CHECK_MESSAGE(p.template get_state<BOOST_MSM_EUML_STATE_NAME(AllOk)&>().get_attribute(exit_counter) == 1,
"AllOk exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(ErrorMode)&>().get_attribute(entry_counter) == 1,
BOOST_CHECK_MESSAGE(p.template get_state<BOOST_MSM_EUML_STATE_NAME(ErrorMode)&>().get_attribute(entry_counter) == 1,
"ErrorMode entry not called correctly");
BOOST_CHECK_MESSAGE(p.current_state()[0] == 0,"Stopped should be active"); //Stopped
BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(Stopped)&>().get_attribute(exit_counter) == 2,
BOOST_CHECK_MESSAGE(p.template get_state<BOOST_MSM_EUML_STATE_NAME(Stopped)&>().get_attribute(exit_counter) == 2,
"Stopped exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(Stopped)&>().get_attribute(entry_counter) == 3,
BOOST_CHECK_MESSAGE(p.template get_state<BOOST_MSM_EUML_STATE_NAME(Stopped)&>().get_attribute(entry_counter) == 3,
"Stopped entry not called correctly");
p.process_event(end_error);
BOOST_CHECK_MESSAGE(p.current_state()[1] == 5,"AllOk should be active"); //AllOk
BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(ErrorMode)&>().get_attribute(exit_counter) == 1,
BOOST_CHECK_MESSAGE(p.template get_state<BOOST_MSM_EUML_STATE_NAME(ErrorMode)&>().get_attribute(exit_counter) == 1,
"ErrorMode exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(AllOk)&>().get_attribute(entry_counter) == 2,
BOOST_CHECK_MESSAGE(p.template get_state<BOOST_MSM_EUML_STATE_NAME(AllOk)&>().get_attribute(entry_counter) == 2,
"AllOk entry not called correctly");
p.process_event(play);
BOOST_CHECK_MESSAGE(p.current_state()[0] == 4,"Playing should be active"); //Playing
BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(Stopped)&>().get_attribute(exit_counter) == 3,
BOOST_CHECK_MESSAGE(p.template get_state<BOOST_MSM_EUML_STATE_NAME(Stopped)&>().get_attribute(exit_counter) == 3,
"Stopped exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<Playing_type&>().get_attribute(entry_counter) == 3,"Playing entry not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<Playing_type&>().get_attribute(entry_counter) == 3,"Playing entry not called correctly");
//test terminate
BOOST_CHECK_MESSAGE(p.current_state()[1] == 5,"AllOk should be active"); //AllOk
p.process_event(do_terminate);
BOOST_CHECK_MESSAGE(p.current_state()[1] == 7,"ErrorTerminate should be active"); //ErrorTerminate
BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(AllOk)&>().get_attribute(exit_counter) == 2,
BOOST_CHECK_MESSAGE(p.template get_state<BOOST_MSM_EUML_STATE_NAME(AllOk)&>().get_attribute(exit_counter) == 2,
"AllOk exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(ErrorTerminate)&>().get_attribute(entry_counter) == 1,
BOOST_CHECK_MESSAGE(p.template get_state<BOOST_MSM_EUML_STATE_NAME(ErrorTerminate)&>().get_attribute(entry_counter) == 1,
"ErrorTerminate entry not called correctly");
// try generating more events
p.process_event(stop);
BOOST_CHECK_MESSAGE(p.current_state()[1] == 7,"ErrorTerminate should be active"); //ErrorTerminate
BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(ErrorTerminate)&>().get_attribute(exit_counter) == 0,
BOOST_CHECK_MESSAGE(p.template get_state<BOOST_MSM_EUML_STATE_NAME(ErrorTerminate)&>().get_attribute(exit_counter) == 0,
"ErrorTerminate exit not called correctly");
BOOST_CHECK_MESSAGE(p.current_state()[0] == 4,"Playing should be active"); //Playing
BOOST_CHECK_MESSAGE(p.get_state<Playing_type&>().get_attribute(exit_counter) == 2,"Playing exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(Stopped)&>().get_attribute(entry_counter) == 3,
BOOST_CHECK_MESSAGE(p.template get_state<Playing_type&>().get_attribute(exit_counter) == 2,"Playing exit not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<BOOST_MSM_EUML_STATE_NAME(Stopped)&>().get_attribute(entry_counter) == 3,
"Stopped entry not called correctly");
p.process_event(end_error());
BOOST_CHECK_MESSAGE(p.current_state()[1] == 7,"ErrorTerminate should be active"); //ErrorTerminate
BOOST_CHECK_MESSAGE(p.current_state()[0] == 4,"Playing should be active"); //Playing
BOOST_CHECK_MESSAGE(p.get_state<Playing_type&>().get_attribute(exit_counter) == 2,"Playing exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(Stopped)&>().get_attribute(entry_counter) == 3,
BOOST_CHECK_MESSAGE(p.template get_state<Playing_type&>().get_attribute(exit_counter) == 2,"Playing exit not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<BOOST_MSM_EUML_STATE_NAME(Stopped)&>().get_attribute(entry_counter) == 3,
"Stopped entry not called correctly");
p.process_event(stop());
BOOST_CHECK_MESSAGE(p.current_state()[1] == 7,"ErrorTerminate should be active"); //ErrorTerminate
BOOST_CHECK_MESSAGE(p.current_state()[0] == 4,"Playing should be active"); //Playing
BOOST_CHECK_MESSAGE(p.get_state<Playing_type&>().get_attribute(exit_counter) == 2,"Playing exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(Stopped)&>().get_attribute(entry_counter) == 3,
BOOST_CHECK_MESSAGE(p.template get_state<Playing_type&>().get_attribute(exit_counter) == 2,"Playing exit not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<BOOST_MSM_EUML_STATE_NAME(Stopped)&>().get_attribute(entry_counter) == 3,
"Stopped entry not called correctly");
}
}
using back0 = hierarchical_state_machine<boost::msm::back::state_machine, boost::msm::back::favor_compile_time>::player;
using back1 = hierarchical_state_machine<boost::msm::back::state_machine, boost::msm::back::favor_compile_time>::Playing_type;
BOOST_MSM_BACK_GENERATE_PROCESS_EVENT(back0);
BOOST_MSM_BACK_GENERATE_PROCESS_EVENT(back1);
+27 -27
View File
@@ -9,11 +9,11 @@
// http://www.boost.org/LICENSE_1_0.txt)
// back-end
#include <boost/msm/back/state_machine.hpp>
#include "BackCommon.hpp"
//front-end
#include <boost/msm/front/state_machine_def.hpp>
#ifndef BOOST_MSM_NONSTANDALONE_TEST
#define BOOST_TEST_MODULE MyTest
#define BOOST_TEST_MODULE serialize_test
#endif
#include <boost/test/unit_test.hpp>
// include headers that implement a archive in simple text format
@@ -213,22 +213,22 @@ namespace
};
// Pick a back-end
typedef msm::back::state_machine<player_> player;
typedef get_test_machines<player_> players;
// static char const* const state_names[] = { "Stopped", "Open", "Empty", "Playing", "Paused" };
BOOST_AUTO_TEST_CASE( my_test )
BOOST_AUTO_TEST_CASE_TEMPLATE( serialize_test, player, players )
{
player p;
p.start();
BOOST_CHECK_MESSAGE(p.get_state<player_::Empty&>().entry_counter == 1,"Empty entry not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<player_::Empty&>().entry_counter == 1,"Empty entry not called correctly");
p.process_event(open_close());
BOOST_CHECK_MESSAGE(p.current_state()[0] == 1,"Open should be active"); //Open
BOOST_CHECK_MESSAGE(p.get_state<player_::Empty&>().exit_counter == 1,"Empty exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::Open&>().entry_counter == 1,"Open entry not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<player_::Empty&>().exit_counter == 1,"Empty exit not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<player_::Open&>().entry_counter == 1,"Open entry not called correctly");
// test the serialization
std::ostringstream ofs;
@@ -249,62 +249,62 @@ namespace
}
// we now use p2 as it was loaded
// check that we kept Empty's data value
BOOST_CHECK_MESSAGE(p2.get_state<player_::Empty&>().some_dummy_data == 3,"Empty not deserialized correctly");
BOOST_CHECK_MESSAGE(p2.template get_state<player_::Empty&>().some_dummy_data == 3,"Empty not deserialized correctly");
BOOST_CHECK_MESSAGE(p2.front_end_data == 4,"Front-end not deserialized correctly");
p.process_event(open_close());
BOOST_CHECK_MESSAGE(p.current_state()[0] == 2,"Empty should be active"); //Empty
BOOST_CHECK_MESSAGE(p.get_state<player_::Open&>().exit_counter == 1,"Open exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::Empty&>().entry_counter == 2,"Empty entry not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<player_::Open&>().exit_counter == 1,"Open exit not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<player_::Empty&>().entry_counter == 2,"Empty entry not called correctly");
BOOST_CHECK_MESSAGE(p.can_close_drawer_counter == 1,"guard not called correctly");
p.process_event(
cd_detected("louie, louie",DISK_DVD));
BOOST_CHECK_MESSAGE(p.current_state()[0] == 2,"Empty should be active"); //Empty
BOOST_CHECK_MESSAGE(p.get_state<player_::Open&>().exit_counter == 1,"Open exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::Empty&>().entry_counter == 2,"Empty entry not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<player_::Open&>().exit_counter == 1,"Open exit not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<player_::Empty&>().entry_counter == 2,"Empty entry not called correctly");
p.process_event(
cd_detected("louie, louie",DISK_CD));
BOOST_CHECK_MESSAGE(p.current_state()[0] == 0,"Stopped should be active"); //Stopped
BOOST_CHECK_MESSAGE(p.get_state<player_::Empty&>().exit_counter == 2,"Empty exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::Stopped&>().entry_counter == 1,"Stopped entry not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<player_::Empty&>().exit_counter == 2,"Empty exit not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<player_::Stopped&>().entry_counter == 1,"Stopped entry not called correctly");
p.process_event(play());
BOOST_CHECK_MESSAGE(p.current_state()[0] == 3,"Playing should be active"); //Playing
BOOST_CHECK_MESSAGE(p.get_state<player_::Stopped&>().exit_counter == 1,"Stopped exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::Playing&>().entry_counter == 1,"Playing entry not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<player_::Stopped&>().exit_counter == 1,"Stopped exit not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<player_::Playing&>().entry_counter == 1,"Playing entry not called correctly");
BOOST_CHECK_MESSAGE(p.start_playback_counter == 1,"action not called correctly");
p.process_event(pause());
BOOST_CHECK_MESSAGE(p.current_state()[0] == 4,"Paused should be active"); //Paused
BOOST_CHECK_MESSAGE(p.get_state<player_::Playing&>().exit_counter == 1,"Playing exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::Paused&>().entry_counter == 1,"Paused entry not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<player_::Playing&>().exit_counter == 1,"Playing exit not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<player_::Paused&>().entry_counter == 1,"Paused entry not called correctly");
// go back to Playing
p.process_event(end_pause());
BOOST_CHECK_MESSAGE(p.current_state()[0] == 3,"Playing should be active"); //Playing
BOOST_CHECK_MESSAGE(p.get_state<player_::Paused&>().exit_counter == 1,"Paused exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::Playing&>().entry_counter == 2,"Playing entry not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<player_::Paused&>().exit_counter == 1,"Paused exit not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<player_::Playing&>().entry_counter == 2,"Playing entry not called correctly");
p.process_event(pause());
BOOST_CHECK_MESSAGE(p.current_state()[0] == 4,"Paused should be active"); //Paused
BOOST_CHECK_MESSAGE(p.get_state<player_::Playing&>().exit_counter == 2,"Playing exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::Paused&>().entry_counter == 2,"Paused entry not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<player_::Playing&>().exit_counter == 2,"Playing exit not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<player_::Paused&>().entry_counter == 2,"Paused entry not called correctly");
p.process_event(stop());
BOOST_CHECK_MESSAGE(p.current_state()[0] == 0,"Stopped should be active"); //Stopped
BOOST_CHECK_MESSAGE(p.get_state<player_::Paused&>().exit_counter == 2,"Paused exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::Stopped&>().entry_counter == 2,"Stopped entry not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<player_::Paused&>().exit_counter == 2,"Paused exit not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<player_::Stopped&>().entry_counter == 2,"Stopped entry not called correctly");
p.process_event(stop());
BOOST_CHECK_MESSAGE(p.current_state()[0] == 0,"Stopped should be active"); //Stopped
BOOST_CHECK_MESSAGE(p.get_state<player_::Stopped&>().exit_counter == 2,"Stopped exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::Stopped&>().entry_counter == 3,"Stopped entry not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<player_::Stopped&>().exit_counter == 2,"Stopped exit not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<player_::Stopped&>().entry_counter == 3,"Stopped entry not called correctly");
}
}
// eliminate object tracking (even if serialized through a pointer)
// at the risk of a programming error creating duplicate objects.
// this is to get rid of warning because p is not const
BOOST_CLASS_TRACKING(player, boost::serialization::track_never)
// BOOST_CLASS_TRACKING(player, boost::serialization::track_never)
+22 -22
View File
@@ -8,11 +8,11 @@
// file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#include <boost/msm/back/state_machine.hpp>
#include "BackCommon.hpp"
#include <boost/msm/front/euml/euml.hpp>
#ifndef BOOST_MSM_NONSTANDALONE_TEST
#define BOOST_TEST_MODULE MyTest
#define BOOST_TEST_MODULE serialize_simple_euml_test
#endif
#include <boost/test/unit_test.hpp>
// include headers that implement a archive in simple text format
@@ -112,24 +112,24 @@ namespace
),
player_) //fsm name
typedef msm::back::state_machine<player_> player;
typedef get_test_machines<player_> players;
// static char const* const state_names[] = { "Stopped", "Paused", "Open", "Empty", "Playing" };
BOOST_AUTO_TEST_CASE( my_test )
BOOST_AUTO_TEST_CASE_TEMPLATE( serialize_simple_euml_test, player, players )
{
player p2;
p2.start();
BOOST_CHECK_MESSAGE(p2.get_state<BOOST_MSM_EUML_STATE_NAME(Empty)&>().get_attribute(entry_counter) == 1,
BOOST_CHECK_MESSAGE(p2.template get_state<BOOST_MSM_EUML_STATE_NAME(Empty)&>().get_attribute(entry_counter) == 1,
"Empty entry not called correctly");
p2.process_event(open_close());
BOOST_CHECK_MESSAGE(p2.current_state()[0] == 2,"Open should be active"); //Open
BOOST_CHECK_MESSAGE(p2.get_state<BOOST_MSM_EUML_STATE_NAME(Empty)&>().get_attribute(exit_counter) == 1,
BOOST_CHECK_MESSAGE(p2.template get_state<BOOST_MSM_EUML_STATE_NAME(Empty)&>().get_attribute(exit_counter) == 1,
"Empty exit not called correctly");
BOOST_CHECK_MESSAGE(p2.get_state<BOOST_MSM_EUML_STATE_NAME(Open)&>().get_attribute(entry_counter) == 1,
BOOST_CHECK_MESSAGE(p2.template get_state<BOOST_MSM_EUML_STATE_NAME(Open)&>().get_attribute(entry_counter) == 1,
"Open entry not called correctly");
// test the serialization
@@ -156,55 +156,55 @@ namespace
p.process_event(
cd_detected("louie, louie",DISK_DVD));
BOOST_CHECK_MESSAGE(p.current_state()[0] == 3,"Empty should be active"); //Empty
BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(Open)&>().get_attribute(exit_counter) == 1,
BOOST_CHECK_MESSAGE(p.template get_state<BOOST_MSM_EUML_STATE_NAME(Open)&>().get_attribute(exit_counter) == 1,
"Open exit not called correctly");
p.process_event(
cd_detected("louie, louie",DISK_CD));
BOOST_CHECK_MESSAGE(p.current_state()[0] == 4,"Playing should be active"); //Playing
BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(Stopped)&>().get_attribute(entry_counter) == 1,
BOOST_CHECK_MESSAGE(p.template get_state<BOOST_MSM_EUML_STATE_NAME(Stopped)&>().get_attribute(entry_counter) == 1,
"Stopped entry not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(Stopped)&>().get_attribute(exit_counter) == 1,
BOOST_CHECK_MESSAGE(p.template get_state<BOOST_MSM_EUML_STATE_NAME(Stopped)&>().get_attribute(exit_counter) == 1,
"Stopped exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(Playing)&>().get_attribute(entry_counter) == 1,
BOOST_CHECK_MESSAGE(p.template get_state<BOOST_MSM_EUML_STATE_NAME(Playing)&>().get_attribute(entry_counter) == 1,
"Playing entry not called correctly");
BOOST_CHECK_MESSAGE(p.get_attribute(start_playback_counter) == 1,"action not called correctly");
BOOST_CHECK_MESSAGE(p.get_attribute(test_fct_counter) == 1,"action not called correctly");
p.process_event(pause());
BOOST_CHECK_MESSAGE(p.current_state()[0] == 1,"Paused should be active"); //Paused
BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(Playing)&>().get_attribute(exit_counter) == 1,
BOOST_CHECK_MESSAGE(p.template get_state<BOOST_MSM_EUML_STATE_NAME(Playing)&>().get_attribute(exit_counter) == 1,
"Playing exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(Paused)&>().get_attribute(entry_counter) == 1,
BOOST_CHECK_MESSAGE(p.template get_state<BOOST_MSM_EUML_STATE_NAME(Paused)&>().get_attribute(entry_counter) == 1,
"Paused entry not called correctly");
// go back to Playing
p.process_event(end_pause());
BOOST_CHECK_MESSAGE(p.current_state()[0] == 4,"Playing should be active"); //Playing
BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(Paused)&>().get_attribute(exit_counter) == 1,
BOOST_CHECK_MESSAGE(p.template get_state<BOOST_MSM_EUML_STATE_NAME(Paused)&>().get_attribute(exit_counter) == 1,
"Paused exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(Playing)&>().get_attribute(entry_counter) == 2,
BOOST_CHECK_MESSAGE(p.template get_state<BOOST_MSM_EUML_STATE_NAME(Playing)&>().get_attribute(entry_counter) == 2,
"Playing entry not called correctly");
p.process_event(pause());
BOOST_CHECK_MESSAGE(p.current_state()[0] == 1,"Paused should be active"); //Paused
BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(Playing)&>().get_attribute(exit_counter) == 2,
BOOST_CHECK_MESSAGE(p.template get_state<BOOST_MSM_EUML_STATE_NAME(Playing)&>().get_attribute(exit_counter) == 2,
"Playing exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(Paused)&>().get_attribute(entry_counter) == 2,
BOOST_CHECK_MESSAGE(p.template get_state<BOOST_MSM_EUML_STATE_NAME(Paused)&>().get_attribute(entry_counter) == 2,
"Paused entry not called correctly");
p.process_event(stop());
BOOST_CHECK_MESSAGE(p.current_state()[0] == 0,"Stopped should be active"); //Stopped
BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(Paused)&>().get_attribute(exit_counter) == 2,
BOOST_CHECK_MESSAGE(p.template get_state<BOOST_MSM_EUML_STATE_NAME(Paused)&>().get_attribute(exit_counter) == 2,
"Paused exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(Stopped)&>().get_attribute(entry_counter) == 2,
BOOST_CHECK_MESSAGE(p.template get_state<BOOST_MSM_EUML_STATE_NAME(Stopped)&>().get_attribute(entry_counter) == 2,
"Stopped entry not called correctly");
p.process_event(stop());
BOOST_CHECK_MESSAGE(p.current_state()[0] == 0,"Stopped should be active"); //Stopped
BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(Stopped)&>().get_attribute(exit_counter) == 2,
BOOST_CHECK_MESSAGE(p.template get_state<BOOST_MSM_EUML_STATE_NAME(Stopped)&>().get_attribute(exit_counter) == 2,
"Stopped exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(Stopped)&>().get_attribute(entry_counter) == 3,
BOOST_CHECK_MESSAGE(p.template get_state<BOOST_MSM_EUML_STATE_NAME(Stopped)&>().get_attribute(entry_counter) == 3,
"Stopped entry not called correctly");
}
}
@@ -212,4 +212,4 @@ namespace
// eliminate object tracking (even if serialized through a pointer)
// at the risk of a programming error creating duplicate objects.
// this is to get rid of warning because p is not const
BOOST_CLASS_TRACKING(player, boost::serialization::track_never)
// BOOST_CLASS_TRACKING(player, boost::serialization::track_never)
+69 -51
View File
@@ -9,11 +9,11 @@
// http://www.boost.org/LICENSE_1_0.txt)
// back-end
#include <boost/msm/back/state_machine.hpp>
#include "BackCommon.hpp"
//front-end
#include <boost/msm/front/state_machine_def.hpp>
#ifndef BOOST_MSM_NONSTANDALONE_TEST
#define BOOST_TEST_MODULE MyTest
#define BOOST_TEST_MODULE serialize_with_history_test
#endif
#include <boost/test/unit_test.hpp>
// include headers that implement a archive in simple text format
@@ -44,9 +44,14 @@ namespace
std::string name;
};
template<template <typename...> class Back, typename Policy = void>
struct hierarchical_state_machine
{
// front-end: define the FSM structure
struct player_ : public msm::front::state_machine_def<player_>
{
BOOST_MSM_TEST_DEFINE_DEPENDENT_TEMPLATES(player_);
unsigned int start_playback_counter;
unsigned int can_close_drawer_counter;
@@ -87,6 +92,8 @@ namespace
struct Playing_ : public msm::front::state_machine_def<Playing_>
{
BOOST_MSM_TEST_DEFINE_DEPENDENT_TEMPLATES(Playing_);
template <class Event,class FSM>
void on_entry(Event const&,FSM& ) {++entry_counter;}
template <class Event,class FSM>
@@ -156,7 +163,7 @@ namespace
}
};
// back-end
typedef msm::back::state_machine<Playing_,msm::back::ShallowHistory<mpl::vector<end_pause> > > Playing;
typedef Back<Playing_,Policy,msm::back::ShallowHistory<mpl::vector<end_pause> > > Playing;
// state not defining any entry or exit
struct Paused : public msm::front::state<>
@@ -223,107 +230,114 @@ namespace
template <class Event,class FSM>
void on_entry(Event const&,FSM& fsm)
{
fsm.template get_state<player_::Stopped&>().entry_counter=0;
fsm.template get_state<player_::Stopped&>().exit_counter=0;
fsm.template get_state<player_::Open&>().entry_counter=0;
fsm.template get_state<player_::Open&>().exit_counter=0;
fsm.template get_state<player_::Empty&>().entry_counter=0;
fsm.template get_state<player_::Empty&>().exit_counter=0;
fsm.template get_state<player_::Playing&>().entry_counter=0;
fsm.template get_state<player_::Playing&>().exit_counter=0;
fsm.template get_state<player_::Playing&>().template get_state<player_::Playing::Song1&>().entry_counter=0;
fsm.template get_state<player_::Playing&>().template get_state<player_::Playing::Song1&>().exit_counter=0;
fsm.template get_state<player_::Playing&>().template get_state<player_::Playing::Song2&>().entry_counter=0;
fsm.template get_state<player_::Playing&>().template get_state<player_::Playing::Song2&>().exit_counter=0;
fsm.template get_state<player_::Playing&>().template get_state<player_::Playing::Song3&>().entry_counter=0;
fsm.template get_state<player_::Playing&>().template get_state<player_::Playing::Song3&>().exit_counter=0;
fsm.template get_state<player_::Paused&>().entry_counter=0;
fsm.template get_state<player_::Paused&>().exit_counter=0;
fsm.template get_state<typename player_::Stopped&>().entry_counter=0;
fsm.template get_state<typename player_::Stopped&>().exit_counter=0;
fsm.template get_state<typename player_::Open&>().entry_counter=0;
fsm.template get_state<typename player_::Open&>().exit_counter=0;
fsm.template get_state<typename player_::Empty&>().entry_counter=0;
fsm.template get_state<typename player_::Empty&>().exit_counter=0;
fsm.template get_state<typename player_::Playing&>().entry_counter=0;
fsm.template get_state<typename player_::Playing&>().exit_counter=0;
fsm.template get_state<typename player_::Playing&>().template get_state<typename player_::Playing::Song1&>().entry_counter=0;
fsm.template get_state<typename player_::Playing&>().template get_state<typename player_::Playing::Song1&>().exit_counter=0;
fsm.template get_state<typename player_::Playing&>().template get_state<typename player_::Playing::Song2&>().entry_counter=0;
fsm.template get_state<typename player_::Playing&>().template get_state<typename player_::Playing::Song2&>().exit_counter=0;
fsm.template get_state<typename player_::Playing&>().template get_state<typename player_::Playing::Song3&>().entry_counter=0;
fsm.template get_state<typename player_::Playing&>().template get_state<typename player_::Playing::Song3&>().exit_counter=0;
fsm.template get_state<typename player_::Paused&>().entry_counter=0;
fsm.template get_state<typename player_::Paused&>().exit_counter=0;
}
};
typedef Back<player_, Policy> player;
};
// Pick a back-end
typedef msm::back::state_machine<player_> player;
typedef boost::mpl::vector<
hierarchical_state_machine<boost::msm::back::state_machine>,
hierarchical_state_machine<boost::msm::back::state_machine, boost::msm::back::favor_compile_time>,
hierarchical_state_machine<boost::msm::back11::state_machine>
> test_machines;
// static char const* const state_names[] = { "Stopped", "Open", "Empty", "Playing", "Paused" };
BOOST_AUTO_TEST_CASE( my_test )
BOOST_AUTO_TEST_CASE_TEMPLATE( serialize_with_history_test, test_machine, test_machines )
{
player p;
typename test_machine::player p;
typedef typename test_machine::player_ player_;
p.start();
BOOST_CHECK_MESSAGE(p.get_state<player_::Empty&>().entry_counter == 1,"Empty entry not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<typename player_::Empty&>().entry_counter == 1,"Empty entry not called correctly");
p.process_event(open_close());
BOOST_CHECK_MESSAGE(p.current_state()[0] == 1,"Open should be active"); //Open
BOOST_CHECK_MESSAGE(p.get_state<player_::Empty&>().exit_counter == 1,"Empty exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::Open&>().entry_counter == 1,"Open entry not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<typename player_::Empty&>().exit_counter == 1,"Empty exit not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<typename player_::Open&>().entry_counter == 1,"Open entry not called correctly");
p.process_event(open_close());
BOOST_CHECK_MESSAGE(p.current_state()[0] == 2,"Empty should be active"); //Empty
BOOST_CHECK_MESSAGE(p.get_state<player_::Open&>().exit_counter == 1,"Open exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::Empty&>().entry_counter == 2,"Empty entry not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<typename player_::Open&>().exit_counter == 1,"Open exit not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<typename player_::Empty&>().entry_counter == 2,"Empty entry not called correctly");
BOOST_CHECK_MESSAGE(p.can_close_drawer_counter == 1,"guard not called correctly");
p.process_event(cd_detected("louie, louie"));
BOOST_CHECK_MESSAGE(p.current_state()[0] == 0,"Stopped should be active"); //Stopped
BOOST_CHECK_MESSAGE(p.get_state<player_::Empty&>().exit_counter == 2,"Empty exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::Stopped&>().entry_counter == 1,"Stopped entry not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<typename player_::Empty&>().exit_counter == 2,"Empty exit not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<typename player_::Stopped&>().entry_counter == 1,"Stopped entry not called correctly");
p.process_event(play());
BOOST_CHECK_MESSAGE(p.current_state()[0] == 3,"Playing should be active"); //Playing
BOOST_CHECK_MESSAGE(p.get_state<player_::Stopped&>().exit_counter == 1,"Stopped exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::Playing&>().entry_counter == 1,"Playing entry not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<typename player_::Stopped&>().exit_counter == 1,"Stopped exit not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<typename player_::Playing&>().entry_counter == 1,"Playing entry not called correctly");
BOOST_CHECK_MESSAGE(p.start_playback_counter == 1,"action not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::Playing&>().current_state()[0] == 0,"Song1 should be active");
BOOST_CHECK_MESSAGE(p.template get_state<typename player_::Playing&>().current_state()[0] == 0,"Song1 should be active");
BOOST_CHECK_MESSAGE(
p.get_state<player_::Playing&>().get_state<player_::Playing::Song1&>().entry_counter == 1,
p.template get_state<typename player_::Playing&>().template get_state<typename player_::Playing::Song1&>().entry_counter == 1,
"Song1 entry not called correctly");
p.process_event(NextSong());
BOOST_CHECK_MESSAGE(p.current_state()[0] == 3,"Playing should be active"); //Playing
BOOST_CHECK_MESSAGE(p.get_state<player_::Playing&>().current_state()[0] == 1,"Song2 should be active");
BOOST_CHECK_MESSAGE(p.template get_state<typename player_::Playing&>().current_state()[0] == 1,"Song2 should be active");
BOOST_CHECK_MESSAGE(
p.get_state<player_::Playing&>().get_state<player_::Playing::Song2&>().entry_counter == 1,
p.template get_state<typename player_::Playing&>().template get_state<typename player_::Playing::Song2&>().entry_counter == 1,
"Song2 entry not called correctly");
BOOST_CHECK_MESSAGE(
p.get_state<player_::Playing&>().get_state<player_::Playing::Song1&>().exit_counter == 1,
p.template get_state<typename player_::Playing&>().template get_state<typename player_::Playing::Song1&>().exit_counter == 1,
"Song1 exit not called correctly");
BOOST_CHECK_MESSAGE(
p.get_state<player_::Playing&>().start_next_song_counter == 0,
p.template get_state<typename player_::Playing&>().start_next_song_counter == 0,
"submachine action not called correctly");
p.process_event(NextSong());
BOOST_CHECK_MESSAGE(p.current_state()[0] == 3,"Playing should be active"); //Playing
BOOST_CHECK_MESSAGE(p.get_state<player_::Playing&>().current_state()[0] == 2,"Song3 should be active");
BOOST_CHECK_MESSAGE(p.template get_state<typename player_::Playing&>().current_state()[0] == 2,"Song3 should be active");
BOOST_CHECK_MESSAGE(
p.get_state<player_::Playing&>().get_state<player_::Playing::Song3&>().entry_counter == 1,
p.template get_state<typename player_::Playing&>().template get_state<typename player_::Playing::Song3&>().entry_counter == 1,
"Song3 entry not called correctly");
BOOST_CHECK_MESSAGE(
p.get_state<player_::Playing&>().get_state<player_::Playing::Song2&>().exit_counter == 1,
p.template get_state<typename player_::Playing&>().template get_state<typename player_::Playing::Song2&>().exit_counter == 1,
"Song2 exit not called correctly");
BOOST_CHECK_MESSAGE(
p.get_state<player_::Playing&>().start_next_song_counter == 1,
p.template get_state<typename player_::Playing&>().start_next_song_counter == 1,
"submachine action not called correctly");
p.process_event(PreviousSong());
BOOST_CHECK_MESSAGE(p.current_state()[0] == 3,"Playing should be active"); //Playing
BOOST_CHECK_MESSAGE(p.get_state<player_::Playing&>().current_state()[0] == 1,"Song2 should be active");
BOOST_CHECK_MESSAGE(p.template get_state<typename player_::Playing&>().current_state()[0] == 1,"Song2 should be active");
BOOST_CHECK_MESSAGE(
p.get_state<player_::Playing&>().get_state<player_::Playing::Song2&>().entry_counter == 2,
p.template get_state<typename player_::Playing&>().template get_state<typename player_::Playing::Song2&>().entry_counter == 2,
"Song2 entry not called correctly");
BOOST_CHECK_MESSAGE(
p.get_state<player_::Playing&>().get_state<player_::Playing::Song3&>().exit_counter == 1,
p.template get_state<typename player_::Playing&>().template get_state<typename player_::Playing::Song3&>().exit_counter == 1,
"Song3 exit not called correctly");
BOOST_CHECK_MESSAGE(
p.get_state<player_::Playing&>().start_prev_song_guard_counter == 1,
p.template get_state<typename player_::Playing&>().start_prev_song_guard_counter == 1,
"submachine guard not called correctly");
p.process_event(pause());
BOOST_CHECK_MESSAGE(p.current_state()[0] == 4,"Paused should be active"); //Paused
BOOST_CHECK_MESSAGE(p.get_state<player_::Playing&>().exit_counter == 1,"Playing exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::Paused&>().entry_counter == 1,"Paused entry not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<typename player_::Playing&>().exit_counter == 1,"Playing exit not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<typename player_::Paused&>().entry_counter == 1,"Paused entry not called correctly");
std::ostringstream ofs;
// save fsm to archive (current state is Pause, Playing is in Song2)
@@ -333,7 +347,7 @@ namespace
oa << p;
}
// reload fsm in state Open
player p2;
typename test_machine::player p2;
{
// create and open an archive for input
std::istringstream ifs(ofs.str());
@@ -344,7 +358,7 @@ namespace
// go back to Playing
p2.process_event(end_pause());
BOOST_CHECK_MESSAGE(p2.current_state()[0] == 3,"Playing should be active"); //Playing
BOOST_CHECK_MESSAGE(p2.get_state<player_::Playing&>().current_state()[0] == 1,"Song2 should be active");
BOOST_CHECK_MESSAGE(p2.template get_state<typename player_::Playing&>().current_state()[0] == 1,"Song2 should be active");
p2.process_event(pause());
BOOST_CHECK_MESSAGE(p2.current_state()[0] == 4,"Paused should be active"); //Paused
@@ -356,11 +370,15 @@ namespace
BOOST_CHECK_MESSAGE(p2.current_state()[0] == 0,"Stopped should be active"); //Stopped
p2.process_event(play());
BOOST_CHECK_MESSAGE(p2.get_state<player_::Playing&>().current_state()[0] == 0,"Song1 should be active");
BOOST_CHECK_MESSAGE(p2.template get_state<typename player_::Playing&>().current_state()[0] == 0,"Song1 should be active");
}
}
// eliminate object tracking (even if serialized through a pointer)
// at the risk of a programming error creating duplicate objects.
// this is to get rid of warning because p is not const
BOOST_CLASS_TRACKING(player, boost::serialization::track_never)
// BOOST_CLASS_TRACKING(player, boost::serialization::track_never)
using back0 = hierarchical_state_machine<boost::msm::back::state_machine, boost::msm::back::favor_compile_time>::player;
using back1 = hierarchical_state_machine<boost::msm::back::state_machine, boost::msm::back::favor_compile_time>::player_::Playing;
BOOST_MSM_BACK_GENERATE_PROCESS_EVENT(back0);
BOOST_MSM_BACK_GENERATE_PROCESS_EVENT(back1);
@@ -9,13 +9,13 @@
// http://www.boost.org/LICENSE_1_0.txt)
// back-end
#include <boost/msm/back11/state_machine.hpp>
#include "BackCommon.hpp"
//front-end
#include <boost/msm/front/state_machine_def.hpp>
#include <boost/msm/front/functor_row.hpp>
#ifndef BOOST_MSM_NONSTANDALONE_TEST
#define BOOST_TEST_MODULE back11_set_states_test
#define BOOST_TEST_MODULE set_states_test
#endif
#include <boost/test/unit_test.hpp>
@@ -68,8 +68,13 @@ namespace
{
};
template<template <typename...> class Back, typename Policy = void>
struct hierarchical_state_machine
{
struct SubFsm_ : public msm::front::state_machine_def<SubFsm_>
{
BOOST_MSM_TEST_DEFINE_DEPENDENT_TEMPLATES(SubFsm_);
template <class Event, class FSM>
void on_entry(Event const& e, FSM& fsm)
{
@@ -95,10 +100,12 @@ namespace
<< " on event " << typeid(e).name() << std::endl;
}
};
typedef msm::back11::state_machine<SubFsm_> SubFsm;
typedef Back<SubFsm_, Policy> SubFsm;
struct Fsm_ : public msm::front::state_machine_def<Fsm_>
{
BOOST_MSM_TEST_DEFINE_DEPENDENT_TEMPLATES(Fsm_);
template <class Event, class FSM>
void on_entry(Event const& e, FSM& fsm)
{
@@ -114,7 +121,7 @@ namespace
typedef SubFsm initial_state;
struct transition_table : mpl::vector<
Row< SubFsm::exit_pt<PseudoExitState>, ExitEvent, TerminateState, none, none >
Row< typename SubFsm::template exit_pt<PseudoExitState>, ExitEvent, TerminateState, none, none >
> {};
template <class FSM, class Event>
@@ -124,12 +131,21 @@ namespace
<< " on event " << typeid(e).name() << std::endl;
}
};
typedef msm::back11::state_machine<Fsm_> Fsm;
typedef Back<Fsm_, Policy> Fsm;
};
// typedef msm::back11::state_machine<Fsm_> Fsm;
typedef boost::mpl::vector<
hierarchical_state_machine<boost::msm::back::state_machine>,
hierarchical_state_machine<boost::msm::back::state_machine, boost::msm::back::favor_compile_time>,
hierarchical_state_machine<boost::msm::back11::state_machine>
> test_machines;
BOOST_AUTO_TEST_CASE(back11_set_states_test)
BOOST_AUTO_TEST_CASE_TEMPLATE(set_states_test, test_machine, test_machines)
{
InputEvent input_event;
typedef typename test_machine::Fsm Fsm;
typedef typename test_machine::SubFsm SubFsm;
std::cout << "\nSubFsms created in constructor\n";
Fsm fsm_subfsms_created_in_constructor(boost::msm::back::states_
@@ -146,3 +162,7 @@ namespace
}
}
using back0 = hierarchical_state_machine<boost::msm::back::state_machine, boost::msm::back::favor_compile_time>::Fsm;
using back1 = hierarchical_state_machine<boost::msm::back::state_machine, boost::msm::back::favor_compile_time>::SubFsm;
BOOST_MSM_BACK_GENERATE_PROCESS_EVENT(back0);
BOOST_MSM_BACK_GENERATE_PROCESS_EVENT(back1);
+25 -25
View File
@@ -8,11 +8,11 @@
// file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#include <boost/msm/back/state_machine.hpp>
#include "BackCommon.hpp"
#include <boost/msm/front/euml/euml.hpp>
#ifndef BOOST_MSM_NONSTANDALONE_TEST
#define BOOST_TEST_MODULE MySimpleEumlTest
#define BOOST_TEST_MODULE simple_euml_test
#endif
#include <boost/test/unit_test.hpp>
@@ -106,90 +106,90 @@ namespace
),
player_) //fsm name
typedef msm::back::state_machine<player_> player;
typedef get_test_machines<player_> players;
// static char const* const state_names[] = { "Stopped", "Paused", "Open", "Empty", "Playing" };
BOOST_AUTO_TEST_CASE(MySimpleEumlTest)
BOOST_AUTO_TEST_CASE_TEMPLATE(simple_euml_test, player, players)
{
player p;
p.start();
BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(Empty)&>().get_attribute(entry_counter) == 1,
BOOST_CHECK_MESSAGE(p.template get_state<BOOST_MSM_EUML_STATE_NAME(Empty)&>().get_attribute(entry_counter) == 1,
"Empty entry not called correctly");
p.process_event(open_close());
BOOST_CHECK_MESSAGE(p.current_state()[0] == 2,"Open should be active"); //Open
BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(Empty)&>().get_attribute(exit_counter) == 1,
BOOST_CHECK_MESSAGE(p.template get_state<BOOST_MSM_EUML_STATE_NAME(Empty)&>().get_attribute(exit_counter) == 1,
"Empty exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(Open)&>().get_attribute(entry_counter) == 1,
BOOST_CHECK_MESSAGE(p.template get_state<BOOST_MSM_EUML_STATE_NAME(Open)&>().get_attribute(entry_counter) == 1,
"Open entry not called correctly");
p.process_event(open_close());
BOOST_CHECK_MESSAGE(p.current_state()[0] == 3,"Empty should be active"); //Empty
BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(Open)&>().get_attribute(exit_counter) == 1,
BOOST_CHECK_MESSAGE(p.template get_state<BOOST_MSM_EUML_STATE_NAME(Open)&>().get_attribute(exit_counter) == 1,
"Open exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(Empty)&>().get_attribute(entry_counter) == 2,
BOOST_CHECK_MESSAGE(p.template get_state<BOOST_MSM_EUML_STATE_NAME(Empty)&>().get_attribute(entry_counter) == 2,
"Empty entry not called correctly");
BOOST_CHECK_MESSAGE(p.get_attribute(can_close_drawer_counter) == 1,"guard not called correctly");
p.process_event(
cd_detected("louie, louie",DISK_DVD));
BOOST_CHECK_MESSAGE(p.current_state()[0] == 3,"Empty should be active"); //Empty
BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(Open)&>().get_attribute(exit_counter) == 1,
BOOST_CHECK_MESSAGE(p.template get_state<BOOST_MSM_EUML_STATE_NAME(Open)&>().get_attribute(exit_counter) == 1,
"Open exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(Empty)&>().get_attribute(entry_counter) == 2,
BOOST_CHECK_MESSAGE(p.template get_state<BOOST_MSM_EUML_STATE_NAME(Empty)&>().get_attribute(entry_counter) == 2,
"Empty entry not called correctly");
p.process_event(
cd_detected("louie, louie",DISK_CD));
BOOST_CHECK_MESSAGE(p.current_state()[0] == 4,"Playing should be active"); //Playing
BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(Empty)&>().get_attribute(exit_counter) == 2,
BOOST_CHECK_MESSAGE(p.template get_state<BOOST_MSM_EUML_STATE_NAME(Empty)&>().get_attribute(exit_counter) == 2,
"Empty exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(Stopped)&>().get_attribute(entry_counter) == 1,
BOOST_CHECK_MESSAGE(p.template get_state<BOOST_MSM_EUML_STATE_NAME(Stopped)&>().get_attribute(entry_counter) == 1,
"Stopped entry not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(Stopped)&>().get_attribute(exit_counter) == 1,
BOOST_CHECK_MESSAGE(p.template get_state<BOOST_MSM_EUML_STATE_NAME(Stopped)&>().get_attribute(exit_counter) == 1,
"Stopped exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(Playing)&>().get_attribute(entry_counter) == 1,
BOOST_CHECK_MESSAGE(p.template get_state<BOOST_MSM_EUML_STATE_NAME(Playing)&>().get_attribute(entry_counter) == 1,
"Playing entry not called correctly");
BOOST_CHECK_MESSAGE(p.get_attribute(start_playback_counter) == 1,"action not called correctly");
BOOST_CHECK_MESSAGE(p.get_attribute(test_fct_counter) == 1,"action not called correctly");
p.process_event(pause());
BOOST_CHECK_MESSAGE(p.current_state()[0] == 1,"Paused should be active"); //Paused
BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(Playing)&>().get_attribute(exit_counter) == 1,
BOOST_CHECK_MESSAGE(p.template get_state<BOOST_MSM_EUML_STATE_NAME(Playing)&>().get_attribute(exit_counter) == 1,
"Playing exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(Paused)&>().get_attribute(entry_counter) == 1,
BOOST_CHECK_MESSAGE(p.template get_state<BOOST_MSM_EUML_STATE_NAME(Paused)&>().get_attribute(entry_counter) == 1,
"Paused entry not called correctly");
// go back to Playing
p.process_event(end_pause());
BOOST_CHECK_MESSAGE(p.current_state()[0] == 4,"Playing should be active"); //Playing
BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(Paused)&>().get_attribute(exit_counter) == 1,
BOOST_CHECK_MESSAGE(p.template get_state<BOOST_MSM_EUML_STATE_NAME(Paused)&>().get_attribute(exit_counter) == 1,
"Paused exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(Playing)&>().get_attribute(entry_counter) == 2,
BOOST_CHECK_MESSAGE(p.template get_state<BOOST_MSM_EUML_STATE_NAME(Playing)&>().get_attribute(entry_counter) == 2,
"Playing entry not called correctly");
p.process_event(pause());
BOOST_CHECK_MESSAGE(p.current_state()[0] == 1,"Paused should be active"); //Paused
BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(Playing)&>().get_attribute(exit_counter) == 2,
BOOST_CHECK_MESSAGE(p.template get_state<BOOST_MSM_EUML_STATE_NAME(Playing)&>().get_attribute(exit_counter) == 2,
"Playing exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(Paused)&>().get_attribute(entry_counter) == 2,
BOOST_CHECK_MESSAGE(p.template get_state<BOOST_MSM_EUML_STATE_NAME(Paused)&>().get_attribute(entry_counter) == 2,
"Paused entry not called correctly");
p.process_event(stop());
BOOST_CHECK_MESSAGE(p.current_state()[0] == 0,"Stopped should be active"); //Stopped
BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(Paused)&>().get_attribute(exit_counter) == 2,
BOOST_CHECK_MESSAGE(p.template get_state<BOOST_MSM_EUML_STATE_NAME(Paused)&>().get_attribute(exit_counter) == 2,
"Paused exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(Stopped)&>().get_attribute(entry_counter) == 2,
BOOST_CHECK_MESSAGE(p.template get_state<BOOST_MSM_EUML_STATE_NAME(Stopped)&>().get_attribute(entry_counter) == 2,
"Stopped entry not called correctly");
p.process_event(stop());
BOOST_CHECK_MESSAGE(p.current_state()[0] == 0,"Stopped should be active"); //Stopped
BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(Stopped)&>().get_attribute(exit_counter) == 2,
BOOST_CHECK_MESSAGE(p.template get_state<BOOST_MSM_EUML_STATE_NAME(Stopped)&>().get_attribute(exit_counter) == 2,
"Stopped exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(Stopped)&>().get_attribute(entry_counter) == 3,
BOOST_CHECK_MESSAGE(p.template get_state<BOOST_MSM_EUML_STATE_NAME(Stopped)&>().get_attribute(entry_counter) == 3,
"Stopped entry not called correctly");
}
}
+25 -25
View File
@@ -8,11 +8,11 @@
// file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#include <boost/msm/back/state_machine.hpp>
#include "BackCommon.hpp"
#include <boost/msm/front/euml/euml.hpp>
#ifndef BOOST_MSM_NONSTANDALONE_TEST
#define BOOST_TEST_MODULE MySimpleEuml2Test
#define BOOST_TEST_MODULE simple_euml_2_test
#endif
#include <boost/test/unit_test.hpp>
@@ -106,90 +106,90 @@ namespace
),
player_) //fsm name
typedef msm::back::state_machine<player_> player;
typedef get_test_machines<player_> players;
// static char const* const state_names[] = { "Stopped", "Paused", "Open", "Empty", "Playing" };
BOOST_AUTO_TEST_CASE(MySimpleEuml2Test)
BOOST_AUTO_TEST_CASE_TEMPLATE(simple_euml_2_test, player, players)
{
player p;
p.start();
BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(Empty)&>().get_attribute(entry_counter) == 1,
BOOST_CHECK_MESSAGE(p.template get_state<BOOST_MSM_EUML_STATE_NAME(Empty)&>().get_attribute(entry_counter) == 1,
"Empty entry not called correctly");
p.process_event(open_close());
BOOST_CHECK_MESSAGE(p.current_state()[0] == 2,"Open should be active"); //Open
BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(Empty)&>().get_attribute(exit_counter) == 1,
BOOST_CHECK_MESSAGE(p.template get_state<BOOST_MSM_EUML_STATE_NAME(Empty)&>().get_attribute(exit_counter) == 1,
"Empty exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(Open)&>().get_attribute(entry_counter) == 1,
BOOST_CHECK_MESSAGE(p.template get_state<BOOST_MSM_EUML_STATE_NAME(Open)&>().get_attribute(entry_counter) == 1,
"Open entry not called correctly");
p.process_event(open_close());
BOOST_CHECK_MESSAGE(p.current_state()[0] == 3,"Empty should be active"); //Empty
BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(Open)&>().get_attribute(exit_counter) == 1,
BOOST_CHECK_MESSAGE(p.template get_state<BOOST_MSM_EUML_STATE_NAME(Open)&>().get_attribute(exit_counter) == 1,
"Open exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(Empty)&>().get_attribute(entry_counter) == 2,
BOOST_CHECK_MESSAGE(p.template get_state<BOOST_MSM_EUML_STATE_NAME(Empty)&>().get_attribute(entry_counter) == 2,
"Empty entry not called correctly");
BOOST_CHECK_MESSAGE(p.get_attribute(can_close_drawer_counter) == 1,"guard not called correctly");
p.process_event(
cd_detected("louie, louie",DISK_DVD));
BOOST_CHECK_MESSAGE(p.current_state()[0] == 3,"Empty should be active"); //Empty
BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(Open)&>().get_attribute(exit_counter) == 1,
BOOST_CHECK_MESSAGE(p.template get_state<BOOST_MSM_EUML_STATE_NAME(Open)&>().get_attribute(exit_counter) == 1,
"Open exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(Empty)&>().get_attribute(entry_counter) == 2,
BOOST_CHECK_MESSAGE(p.template get_state<BOOST_MSM_EUML_STATE_NAME(Empty)&>().get_attribute(entry_counter) == 2,
"Empty entry not called correctly");
p.process_event(
cd_detected("louie, louie",DISK_CD));
BOOST_CHECK_MESSAGE(p.current_state()[0] == 4,"Playing should be active"); //Playing
BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(Empty)&>().get_attribute(exit_counter) == 2,
BOOST_CHECK_MESSAGE(p.template get_state<BOOST_MSM_EUML_STATE_NAME(Empty)&>().get_attribute(exit_counter) == 2,
"Empty exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(Stopped)&>().get_attribute(entry_counter) == 1,
BOOST_CHECK_MESSAGE(p.template get_state<BOOST_MSM_EUML_STATE_NAME(Stopped)&>().get_attribute(entry_counter) == 1,
"Stopped entry not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(Stopped)&>().get_attribute(exit_counter) == 1,
BOOST_CHECK_MESSAGE(p.template get_state<BOOST_MSM_EUML_STATE_NAME(Stopped)&>().get_attribute(exit_counter) == 1,
"Stopped exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(Playing)&>().get_attribute(entry_counter) == 1,
BOOST_CHECK_MESSAGE(p.template get_state<BOOST_MSM_EUML_STATE_NAME(Playing)&>().get_attribute(entry_counter) == 1,
"Playing entry not called correctly");
BOOST_CHECK_MESSAGE(p.get_attribute(start_playback_counter) == 1,"action not called correctly");
BOOST_CHECK_MESSAGE(p.get_attribute(test_fct_counter) == 1,"action not called correctly");
p.process_event(pause());
BOOST_CHECK_MESSAGE(p.current_state()[0] == 1,"Paused should be active"); //Paused
BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(Playing)&>().get_attribute(exit_counter) == 1,
BOOST_CHECK_MESSAGE(p.template get_state<BOOST_MSM_EUML_STATE_NAME(Playing)&>().get_attribute(exit_counter) == 1,
"Playing exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(Paused)&>().get_attribute(entry_counter) == 1,
BOOST_CHECK_MESSAGE(p.template get_state<BOOST_MSM_EUML_STATE_NAME(Paused)&>().get_attribute(entry_counter) == 1,
"Paused entry not called correctly");
// go back to Playing
p.process_event(end_pause());
BOOST_CHECK_MESSAGE(p.current_state()[0] == 4,"Playing should be active"); //Playing
BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(Paused)&>().get_attribute(exit_counter) == 1,
BOOST_CHECK_MESSAGE(p.template get_state<BOOST_MSM_EUML_STATE_NAME(Paused)&>().get_attribute(exit_counter) == 1,
"Paused exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(Playing)&>().get_attribute(entry_counter) == 2,
BOOST_CHECK_MESSAGE(p.template get_state<BOOST_MSM_EUML_STATE_NAME(Playing)&>().get_attribute(entry_counter) == 2,
"Playing entry not called correctly");
p.process_event(pause());
BOOST_CHECK_MESSAGE(p.current_state()[0] == 1,"Paused should be active"); //Paused
BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(Playing)&>().get_attribute(exit_counter) == 2,
BOOST_CHECK_MESSAGE(p.template get_state<BOOST_MSM_EUML_STATE_NAME(Playing)&>().get_attribute(exit_counter) == 2,
"Playing exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(Paused)&>().get_attribute(entry_counter) == 2,
BOOST_CHECK_MESSAGE(p.template get_state<BOOST_MSM_EUML_STATE_NAME(Paused)&>().get_attribute(entry_counter) == 2,
"Paused entry not called correctly");
p.process_event(stop());
BOOST_CHECK_MESSAGE(p.current_state()[0] == 0,"Stopped should be active"); //Stopped
BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(Paused)&>().get_attribute(exit_counter) == 2,
BOOST_CHECK_MESSAGE(p.template get_state<BOOST_MSM_EUML_STATE_NAME(Paused)&>().get_attribute(exit_counter) == 2,
"Paused exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(Stopped)&>().get_attribute(entry_counter) == 2,
BOOST_CHECK_MESSAGE(p.template get_state<BOOST_MSM_EUML_STATE_NAME(Stopped)&>().get_attribute(entry_counter) == 2,
"Stopped entry not called correctly");
p.process_event(stop());
BOOST_CHECK_MESSAGE(p.current_state()[0] == 0,"Stopped should be active"); //Stopped
BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(Stopped)&>().get_attribute(exit_counter) == 2,
BOOST_CHECK_MESSAGE(p.template get_state<BOOST_MSM_EUML_STATE_NAME(Stopped)&>().get_attribute(exit_counter) == 2,
"Stopped exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(Stopped)&>().get_attribute(entry_counter) == 3,
BOOST_CHECK_MESSAGE(p.template get_state<BOOST_MSM_EUML_STATE_NAME(Stopped)&>().get_attribute(entry_counter) == 3,
"Stopped entry not called correctly");
}
}
+25 -25
View File
@@ -9,11 +9,11 @@
// http://www.boost.org/LICENSE_1_0.txt)
// back-end
#include <boost/msm/back/state_machine.hpp>
#include "BackCommon.hpp"
//front-end
#include <boost/msm/front/state_machine_def.hpp>
#ifndef BOOST_MSM_NONSTANDALONE_TEST
#define BOOST_TEST_MODULE MyTest
#define BOOST_TEST_MODULE simple_internal_test
#endif
#include <boost/test/unit_test.hpp>
@@ -197,17 +197,17 @@ namespace
};
// Pick a back-end
typedef msm::back::state_machine<player_> player;
typedef get_test_machines<player_> players;
// static char const* const state_names[] = { "Stopped", "Open", "Empty", "Playing", "Paused" };
BOOST_AUTO_TEST_CASE( my_test )
BOOST_AUTO_TEST_CASE_TEMPLATE( simple_internal_test, player, players )
{
player p;
p.start();
BOOST_CHECK_MESSAGE(p.get_state<player_::Empty&>().entry_counter == 1,"Empty entry not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<player_::Empty&>().entry_counter == 1,"Empty entry not called correctly");
// internal events
p.process_event(to_ignore());
p.process_event(internal_evt());
@@ -216,60 +216,60 @@ namespace
p.process_event(open_close());
BOOST_CHECK_MESSAGE(p.current_state()[0] == 1,"Open should be active"); //Open
BOOST_CHECK_MESSAGE(p.get_state<player_::Empty&>().exit_counter == 1,"Empty exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::Open&>().entry_counter == 1,"Open entry not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<player_::Empty&>().exit_counter == 1,"Empty exit not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<player_::Open&>().entry_counter == 1,"Open entry not called correctly");
p.process_event(open_close());
BOOST_CHECK_MESSAGE(p.current_state()[0] == 2,"Empty should be active"); //Empty
BOOST_CHECK_MESSAGE(p.get_state<player_::Open&>().exit_counter == 1,"Open exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::Empty&>().entry_counter == 2,"Empty entry not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<player_::Open&>().exit_counter == 1,"Open exit not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<player_::Empty&>().entry_counter == 2,"Empty entry not called correctly");
BOOST_CHECK_MESSAGE(p.can_close_drawer_counter == 1,"guard not called correctly");
p.process_event(
cd_detected("louie, louie",DISK_DVD));
BOOST_CHECK_MESSAGE(p.current_state()[0] == 2,"Empty should be active"); //Empty
BOOST_CHECK_MESSAGE(p.get_state<player_::Open&>().exit_counter == 1,"Open exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::Empty&>().entry_counter == 2,"Empty entry not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<player_::Open&>().exit_counter == 1,"Open exit not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<player_::Empty&>().entry_counter == 2,"Empty entry not called correctly");
BOOST_CHECK_MESSAGE(p.internal_guard_counter == 2,"Internal guard not called correctly");
p.process_event(
cd_detected("louie, louie",DISK_CD));
BOOST_CHECK_MESSAGE(p.current_state()[0] == 0,"Stopped should be active"); //Stopped
BOOST_CHECK_MESSAGE(p.get_state<player_::Empty&>().exit_counter == 2,"Empty exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::Stopped&>().entry_counter == 1,"Stopped entry not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<player_::Empty&>().exit_counter == 2,"Empty exit not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<player_::Stopped&>().entry_counter == 1,"Stopped entry not called correctly");
BOOST_CHECK_MESSAGE(p.internal_guard_counter == 3,"Internal guard not called correctly");
p.process_event(play());
BOOST_CHECK_MESSAGE(p.current_state()[0] == 3,"Playing should be active"); //Playing
BOOST_CHECK_MESSAGE(p.get_state<player_::Stopped&>().exit_counter == 1,"Stopped exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::Playing&>().entry_counter == 1,"Playing entry not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<player_::Stopped&>().exit_counter == 1,"Stopped exit not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<player_::Playing&>().entry_counter == 1,"Playing entry not called correctly");
BOOST_CHECK_MESSAGE(p.start_playback_counter == 1,"action not called correctly");
p.process_event(pause());
BOOST_CHECK_MESSAGE(p.current_state()[0] == 4,"Paused should be active"); //Paused
BOOST_CHECK_MESSAGE(p.get_state<player_::Playing&>().exit_counter == 1,"Playing exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::Paused&>().entry_counter == 1,"Paused entry not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<player_::Playing&>().exit_counter == 1,"Playing exit not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<player_::Paused&>().entry_counter == 1,"Paused entry not called correctly");
// go back to Playing
p.process_event(end_pause());
BOOST_CHECK_MESSAGE(p.current_state()[0] == 3,"Playing should be active"); //Playing
BOOST_CHECK_MESSAGE(p.get_state<player_::Paused&>().exit_counter == 1,"Paused exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::Playing&>().entry_counter == 2,"Playing entry not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<player_::Paused&>().exit_counter == 1,"Paused exit not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<player_::Playing&>().entry_counter == 2,"Playing entry not called correctly");
p.process_event(pause());
BOOST_CHECK_MESSAGE(p.current_state()[0] == 4,"Paused should be active"); //Paused
BOOST_CHECK_MESSAGE(p.get_state<player_::Playing&>().exit_counter == 2,"Playing exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::Paused&>().entry_counter == 2,"Paused entry not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<player_::Playing&>().exit_counter == 2,"Playing exit not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<player_::Paused&>().entry_counter == 2,"Paused entry not called correctly");
p.process_event(stop());
BOOST_CHECK_MESSAGE(p.current_state()[0] == 0,"Stopped should be active"); //Stopped
BOOST_CHECK_MESSAGE(p.get_state<player_::Paused&>().exit_counter == 2,"Paused exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::Stopped&>().entry_counter == 2,"Stopped entry not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<player_::Paused&>().exit_counter == 2,"Paused exit not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<player_::Stopped&>().entry_counter == 2,"Stopped entry not called correctly");
p.process_event(stop());
BOOST_CHECK_MESSAGE(p.current_state()[0] == 0,"Stopped should be active"); //Stopped
BOOST_CHECK_MESSAGE(p.get_state<player_::Stopped&>().exit_counter == 2,"Stopped exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::Stopped&>().entry_counter == 3,"Stopped entry not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<player_::Stopped&>().exit_counter == 2,"Stopped exit not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<player_::Stopped&>().entry_counter == 3,"Stopped entry not called correctly");
}
}
+28 -27
View File
@@ -8,10 +8,10 @@
// file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#include <boost/msm/back/state_machine.hpp>
#include "BackCommon.hpp"
#include <boost/msm/front/euml/euml.hpp>
#ifndef BOOST_MSM_NONSTANDALONE_TEST
#define BOOST_TEST_MODULE MySimpleInternalEumlTest
#define BOOST_TEST_MODULE simple_internal_euml_test
#endif
#include <boost/test/unit_test.hpp>
@@ -153,17 +153,18 @@ namespace
),
player_) //fsm name
typedef msm::back::state_machine<player_> player;
// typedef msm::back::state_machine<player_> player;
typedef get_test_machines<player_> players;
// static char const* const state_names[] = { "Stopped", "Paused", "Open", "Empty", "Playing" };
BOOST_AUTO_TEST_CASE( simple_internal_euml_test )
BOOST_AUTO_TEST_CASE_TEMPLATE( simple_internal_euml_test, player, players )
{
player p;
p.start();
BOOST_CHECK_MESSAGE(p.get_state<Empty_impl&>().get_attribute(entry_counter) == 1,
BOOST_CHECK_MESSAGE(p.template get_state<Empty_impl&>().get_attribute(entry_counter) == 1,
"Empty entry not called correctly");
// internal events
@@ -171,82 +172,82 @@ namespace
p.process_event(internal_evt);
BOOST_CHECK_MESSAGE(p.get_attribute(internal_action_counter) == 1,"Internal action not called correctly");
BOOST_CHECK_MESSAGE(p.get_attribute(internal_guard_counter) == 1,"Internal guard not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<Empty_impl&>().get_attribute(empty_internal_action_counter) == 0,
BOOST_CHECK_MESSAGE(p.template get_state<Empty_impl&>().get_attribute(empty_internal_action_counter) == 0,
"Empty internal action not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<Empty_impl&>().get_attribute(empty_internal_guard_counter) == 1,
BOOST_CHECK_MESSAGE(p.template get_state<Empty_impl&>().get_attribute(empty_internal_guard_counter) == 1,
"Empty internal guard not called correctly");
p.process_event(open_close());
BOOST_CHECK_MESSAGE(p.current_state()[0] == 2,"Open should be active"); //Open
BOOST_CHECK_MESSAGE(p.get_state<Empty_impl&>().get_attribute(exit_counter) == 1,
BOOST_CHECK_MESSAGE(p.template get_state<Empty_impl&>().get_attribute(exit_counter) == 1,
"Empty exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<Empty_impl&>().get_attribute(entry_counter) == 1,
BOOST_CHECK_MESSAGE(p.template get_state<Empty_impl&>().get_attribute(entry_counter) == 1,
"Open entry not called correctly");
p.process_event(open_close());
BOOST_CHECK_MESSAGE(p.current_state()[0] == 3,"Empty should be active"); //Empty
BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(Open)&>().get_attribute(exit_counter) == 1,
BOOST_CHECK_MESSAGE(p.template get_state<BOOST_MSM_EUML_STATE_NAME(Open)&>().get_attribute(exit_counter) == 1,
"Open exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<Empty_impl&>().get_attribute(entry_counter) == 2,
BOOST_CHECK_MESSAGE(p.template get_state<Empty_impl&>().get_attribute(entry_counter) == 2,
"Empty entry not called correctly");
BOOST_CHECK_MESSAGE(p.get_attribute(can_close_drawer_counter) == 1,"guard not called correctly");
p.process_event(
cd_detected("louie, louie",DISK_DVD));
BOOST_CHECK_MESSAGE(p.current_state()[0] == 3,"Empty should be active"); //Empty
BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(Open)&>().get_attribute(exit_counter) == 1,
BOOST_CHECK_MESSAGE(p.template get_state<BOOST_MSM_EUML_STATE_NAME(Open)&>().get_attribute(exit_counter) == 1,
"Open exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<Empty_impl&>().get_attribute(entry_counter) == 2,
BOOST_CHECK_MESSAGE(p.template get_state<Empty_impl&>().get_attribute(entry_counter) == 2,
"Empty entry not called correctly");
p.process_event(
cd_detected("louie, louie",DISK_CD));
p.process_event(play);
BOOST_CHECK_MESSAGE(p.current_state()[0] == 4,"Playing should be active"); //Playing
BOOST_CHECK_MESSAGE(p.get_state<Empty_impl&>().get_attribute(exit_counter) == 2,
BOOST_CHECK_MESSAGE(p.template get_state<Empty_impl&>().get_attribute(exit_counter) == 2,
"Empty exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(Stopped)&>().get_attribute(entry_counter) == 1,
BOOST_CHECK_MESSAGE(p.template get_state<BOOST_MSM_EUML_STATE_NAME(Stopped)&>().get_attribute(entry_counter) == 1,
"Stopped entry not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(Stopped)&>().get_attribute(exit_counter) == 1,
BOOST_CHECK_MESSAGE(p.template get_state<BOOST_MSM_EUML_STATE_NAME(Stopped)&>().get_attribute(exit_counter) == 1,
"Stopped exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(Playing)&>().get_attribute(entry_counter) == 1,
BOOST_CHECK_MESSAGE(p.template get_state<BOOST_MSM_EUML_STATE_NAME(Playing)&>().get_attribute(entry_counter) == 1,
"Playing entry not called correctly");
BOOST_CHECK_MESSAGE(p.get_attribute(start_playback_counter) == 1,"action not called correctly");
p.process_event(pause());
BOOST_CHECK_MESSAGE(p.current_state()[0] == 1,"Paused should be active"); //Paused
BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(Playing)&>().get_attribute(exit_counter) == 1,
BOOST_CHECK_MESSAGE(p.template get_state<BOOST_MSM_EUML_STATE_NAME(Playing)&>().get_attribute(exit_counter) == 1,
"Playing exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(Paused)&>().get_attribute(entry_counter) == 1,
BOOST_CHECK_MESSAGE(p.template get_state<BOOST_MSM_EUML_STATE_NAME(Paused)&>().get_attribute(entry_counter) == 1,
"Paused entry not called correctly");
// go back to Playing
p.process_event(end_pause());
BOOST_CHECK_MESSAGE(p.current_state()[0] == 4,"Playing should be active"); //Playing
BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(Paused)&>().get_attribute(exit_counter) == 1,
BOOST_CHECK_MESSAGE(p.template get_state<BOOST_MSM_EUML_STATE_NAME(Paused)&>().get_attribute(exit_counter) == 1,
"Paused exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(Playing)&>().get_attribute(entry_counter) == 2,
BOOST_CHECK_MESSAGE(p.template get_state<BOOST_MSM_EUML_STATE_NAME(Playing)&>().get_attribute(entry_counter) == 2,
"Playing entry not called correctly");
p.process_event(pause());
BOOST_CHECK_MESSAGE(p.current_state()[0] == 1,"Paused should be active"); //Paused
BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(Playing)&>().get_attribute(exit_counter) == 2,
BOOST_CHECK_MESSAGE(p.template get_state<BOOST_MSM_EUML_STATE_NAME(Playing)&>().get_attribute(exit_counter) == 2,
"Playing exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(Paused)&>().get_attribute(entry_counter) == 2,
BOOST_CHECK_MESSAGE(p.template get_state<BOOST_MSM_EUML_STATE_NAME(Paused)&>().get_attribute(entry_counter) == 2,
"Paused entry not called correctly");
p.process_event(stop());
BOOST_CHECK_MESSAGE(p.current_state()[0] == 0,"Stopped should be active"); //Stopped
BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(Paused)&>().get_attribute(exit_counter) == 2,
BOOST_CHECK_MESSAGE(p.template get_state<BOOST_MSM_EUML_STATE_NAME(Paused)&>().get_attribute(exit_counter) == 2,
"Paused exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(Stopped)&>().get_attribute(entry_counter) == 2,
BOOST_CHECK_MESSAGE(p.template get_state<BOOST_MSM_EUML_STATE_NAME(Stopped)&>().get_attribute(entry_counter) == 2,
"Stopped entry not called correctly");
p.process_event(stop());
BOOST_CHECK_MESSAGE(p.current_state()[0] == 0,"Stopped should be active"); //Stopped
BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(Stopped)&>().get_attribute(exit_counter) == 2,
BOOST_CHECK_MESSAGE(p.template get_state<BOOST_MSM_EUML_STATE_NAME(Stopped)&>().get_attribute(exit_counter) == 2,
"Stopped exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(Stopped)&>().get_attribute(entry_counter) == 3,
BOOST_CHECK_MESSAGE(p.template get_state<BOOST_MSM_EUML_STATE_NAME(Stopped)&>().get_attribute(entry_counter) == 3,
"Stopped entry not called correctly");
}
}
+27 -27
View File
@@ -9,13 +9,13 @@
// http://www.boost.org/LICENSE_1_0.txt)
// back-end
#include <boost/msm/back/state_machine.hpp>
#include "BackCommon.hpp"
//front-end
#include <boost/msm/front/state_machine_def.hpp>
#include <boost/msm/front/functor_row.hpp>
#include <boost/msm/front/euml/common.hpp>
#ifndef BOOST_MSM_NONSTANDALONE_TEST
#define BOOST_TEST_MODULE MyTest
#define BOOST_TEST_MODULE simple_internal_functors_test
#endif
#include <boost/test/unit_test.hpp>
@@ -251,81 +251,81 @@ namespace
};
// Pick a back-end
typedef msm::back::state_machine<player_> player;
typedef get_test_machines<player_> players;
// static char const* const state_names[] = { "Stopped", "Open", "Empty", "Playing", "Paused" };
BOOST_AUTO_TEST_CASE( simple_internal_functors_test )
BOOST_AUTO_TEST_CASE_TEMPLATE( simple_internal_functors_test, player, players )
{
player p;
p.start();
BOOST_CHECK_MESSAGE(p.get_state<player_::Empty&>().entry_counter == 1,"Empty entry not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<player_::Empty&>().entry_counter == 1,"Empty entry not called correctly");
// internal events
p.process_event(to_ignore());
p.process_event(internal_evt());
BOOST_CHECK_MESSAGE(p.internal_action_counter == 1,"Internal action not called correctly");
BOOST_CHECK_MESSAGE(p.internal_guard_counter == 1,"Internal guard not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::Empty&>().empty_internal_action_counter == 0,"Empty internal action not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::Empty&>().empty_internal_guard_counter == 1,"Empty internal guard not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<player_::Empty&>().empty_internal_action_counter == 0,"Empty internal action not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<player_::Empty&>().empty_internal_guard_counter == 1,"Empty internal guard not called correctly");
p.process_event(open_close());
BOOST_CHECK_MESSAGE(p.current_state()[0] == 1,"Open should be active"); //Open
BOOST_CHECK_MESSAGE(p.get_state<player_::Empty&>().exit_counter == 1,"Empty exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::Open&>().entry_counter == 1,"Open entry not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<player_::Empty&>().exit_counter == 1,"Empty exit not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<player_::Open&>().entry_counter == 1,"Open entry not called correctly");
p.process_event(open_close());
BOOST_CHECK_MESSAGE(p.current_state()[0] == 2,"Empty should be active"); //Empty
BOOST_CHECK_MESSAGE(p.get_state<player_::Open&>().exit_counter == 1,"Open exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::Empty&>().entry_counter == 2,"Empty entry not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<player_::Open&>().exit_counter == 1,"Open exit not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<player_::Empty&>().entry_counter == 2,"Empty entry not called correctly");
BOOST_CHECK_MESSAGE(p.can_close_drawer_counter == 1,"guard not called correctly");
p.process_event(
cd_detected("louie, louie",DISK_DVD));
BOOST_CHECK_MESSAGE(p.current_state()[0] == 2,"Empty should be active"); //Empty
BOOST_CHECK_MESSAGE(p.get_state<player_::Open&>().exit_counter == 1,"Open exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::Empty&>().entry_counter == 2,"Empty entry not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<player_::Open&>().exit_counter == 1,"Open exit not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<player_::Empty&>().entry_counter == 2,"Empty entry not called correctly");
BOOST_CHECK_MESSAGE(p.internal_guard_counter == 2,"Internal guard not called correctly");
p.process_event(
cd_detected("louie, louie",DISK_CD));
BOOST_CHECK_MESSAGE(p.current_state()[0] == 0,"Stopped should be active"); //Stopped
BOOST_CHECK_MESSAGE(p.get_state<player_::Empty&>().exit_counter == 2,"Empty exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::Stopped&>().entry_counter == 1,"Stopped entry not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<player_::Empty&>().exit_counter == 2,"Empty exit not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<player_::Stopped&>().entry_counter == 1,"Stopped entry not called correctly");
BOOST_CHECK_MESSAGE(p.internal_guard_counter == 3,"Internal guard not called correctly");
p.process_event(play());
BOOST_CHECK_MESSAGE(p.current_state()[0] == 3,"Playing should be active"); //Playing
BOOST_CHECK_MESSAGE(p.get_state<player_::Stopped&>().exit_counter == 1,"Stopped exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::Playing&>().entry_counter == 1,"Playing entry not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<player_::Stopped&>().exit_counter == 1,"Stopped exit not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<player_::Playing&>().entry_counter == 1,"Playing entry not called correctly");
BOOST_CHECK_MESSAGE(p.start_playback_counter == 1,"action not called correctly");
p.process_event(pause());
BOOST_CHECK_MESSAGE(p.current_state()[0] == 4,"Paused should be active"); //Paused
BOOST_CHECK_MESSAGE(p.get_state<player_::Playing&>().exit_counter == 1,"Playing exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::Paused&>().entry_counter == 1,"Paused entry not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<player_::Playing&>().exit_counter == 1,"Playing exit not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<player_::Paused&>().entry_counter == 1,"Paused entry not called correctly");
// go back to Playing
p.process_event(end_pause());
BOOST_CHECK_MESSAGE(p.current_state()[0] == 3,"Playing should be active"); //Playing
BOOST_CHECK_MESSAGE(p.get_state<player_::Paused&>().exit_counter == 1,"Paused exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::Playing&>().entry_counter == 2,"Playing entry not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<player_::Paused&>().exit_counter == 1,"Paused exit not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<player_::Playing&>().entry_counter == 2,"Playing entry not called correctly");
p.process_event(pause());
BOOST_CHECK_MESSAGE(p.current_state()[0] == 4,"Paused should be active"); //Paused
BOOST_CHECK_MESSAGE(p.get_state<player_::Playing&>().exit_counter == 2,"Playing exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::Paused&>().entry_counter == 2,"Paused entry not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<player_::Playing&>().exit_counter == 2,"Playing exit not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<player_::Paused&>().entry_counter == 2,"Paused entry not called correctly");
p.process_event(stop());
BOOST_CHECK_MESSAGE(p.current_state()[0] == 0,"Stopped should be active"); //Stopped
BOOST_CHECK_MESSAGE(p.get_state<player_::Paused&>().exit_counter == 2,"Paused exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::Stopped&>().entry_counter == 2,"Stopped entry not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<player_::Paused&>().exit_counter == 2,"Paused exit not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<player_::Stopped&>().entry_counter == 2,"Stopped entry not called correctly");
p.process_event(stop());
BOOST_CHECK_MESSAGE(p.current_state()[0] == 0,"Stopped should be active"); //Stopped
BOOST_CHECK_MESSAGE(p.get_state<player_::Stopped&>().exit_counter == 2,"Stopped exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::Stopped&>().entry_counter == 3,"Stopped entry not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<player_::Stopped&>().exit_counter == 2,"Stopped exit not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<player_::Stopped&>().entry_counter == 3,"Stopped entry not called correctly");
}
}
@@ -10,14 +10,14 @@
// back-end
#include <boost/msm/back11/state_machine.hpp>
#include "BackCommon.hpp"
//front-end
#include <boost/msm/front/state_machine_def.hpp>
#include <boost/msm/front/puml/puml.hpp>
#include <PumlCommon.hpp>
#ifndef BOOST_MSM_NONSTANDALONE_TEST
#define BOOST_TEST_MODULE back11_simple_internal_with_puml
#define BOOST_TEST_MODULE simple_internal_with_puml
#endif
#include <boost/test/unit_test.hpp>
@@ -79,77 +79,77 @@ namespace
}
};
// Pick a back-end
typedef msm::back11::state_machine<player_> player;
typedef get_test_machines<player_> players;
BOOST_AUTO_TEST_CASE( back11_simple_internal_with_puml_test )
BOOST_AUTO_TEST_CASE_TEMPLATE( simple_internal_with_puml_test, player, players )
{
player p;
p.start();
BOOST_CHECK_MESSAGE(p.get_state<State<by_name("Empty")>&>().entry_counter == 1, "Empty entry not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<State<by_name("Empty")>&>().entry_counter == 1, "Empty entry not called correctly");
// internal events
p.process_event(Event<by_name("to_ignore")>{});
p.process_event(Event<by_name("internal_evt")>{});
BOOST_CHECK_MESSAGE(p.internal_action_counter == 1, "Internal action not called correctly");
BOOST_CHECK_MESSAGE(p.internal_guard_counter == 1, "Internal guard not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<State<by_name("Empty")>&>().empty_internal_action_counter == 0, "Empty internal action not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<State<by_name("Empty")>&>().empty_internal_guard_counter == 1, "Empty internal guard not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<State<by_name("Empty")>&>().empty_internal_action_counter == 0, "Empty internal action not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<State<by_name("Empty")>&>().empty_internal_guard_counter == 1, "Empty internal guard not called correctly");
p.process_event(Event<by_name("open_close")>{});
BOOST_CHECK_MESSAGE(p.current_state()[0] == 1,"Open should be active"); //Open
BOOST_CHECK_MESSAGE(p.get_state<State<by_name("Empty")>&>().exit_counter == 1,"Empty exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<State<by_name("Open")>&>().entry_counter == 1,"Open entry not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<State<by_name("Empty")>&>().exit_counter == 1,"Empty exit not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<State<by_name("Open")>&>().entry_counter == 1,"Open entry not called correctly");
p.process_event(Event<by_name("open_close")>{});
BOOST_CHECK_MESSAGE(p.current_state()[0] == 2,"Empty should be active"); //Empty
BOOST_CHECK_MESSAGE(p.get_state<State<by_name("Open")>&>().exit_counter == 1,"Open exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<State<by_name("Empty")>&>().entry_counter == 2,"Empty entry not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<State<by_name("Open")>&>().exit_counter == 1,"Open exit not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<State<by_name("Empty")>&>().entry_counter == 2,"Empty entry not called correctly");
BOOST_CHECK_MESSAGE(p.can_close_drawer_counter == 1,"guard not called correctly");
p.process_event(Event<by_name("cd_detected")>{"louie, louie", DISK_DVD});
BOOST_CHECK_MESSAGE(p.current_state()[0] == 2,"Empty should be active"); //Empty
BOOST_CHECK_MESSAGE(p.get_state<State<by_name("Open")>&>().exit_counter == 1,"Open exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<State<by_name("Empty")>&>().entry_counter == 2,"Empty entry not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<State<by_name("Open")>&>().exit_counter == 1,"Open exit not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<State<by_name("Empty")>&>().entry_counter == 2,"Empty entry not called correctly");
p.process_event(Event<by_name("cd_detected")>{"louie, louie", DISK_CD});
BOOST_CHECK_MESSAGE(p.current_state()[0] == 0, "Stopped should be active"); //Stopped
BOOST_CHECK_MESSAGE(p.get_state<State<by_name("Empty")>&>().exit_counter == 2,"Empty exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<State<by_name("Stopped")>&>().entry_counter == 1,"Stopped entry not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<State<by_name("Empty")>&>().exit_counter == 2,"Empty exit not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<State<by_name("Stopped")>&>().entry_counter == 1,"Stopped entry not called correctly");
BOOST_CHECK_MESSAGE(p.internal_guard_counter == 3, "Internal guard not called correctly");
p.process_event(Event<by_name("play")>{});
BOOST_CHECK_MESSAGE(p.current_state()[0] == 3, "Playing should be active"); //Playing
BOOST_CHECK_MESSAGE(p.get_state<State<by_name("Stopped")>&>().exit_counter == 1, "Stopped exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<State<by_name("Playing")>&>().entry_counter == 1, "Playing entry not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<State<by_name("Stopped")>&>().exit_counter == 1, "Stopped exit not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<State<by_name("Playing")>&>().entry_counter == 1, "Playing entry not called correctly");
BOOST_CHECK_MESSAGE(p.start_playback_counter == 1, "action not called correctly");
p.process_event(Event<by_name("pause")>{});
BOOST_CHECK_MESSAGE(p.current_state()[0] == 4, "Paused should be active"); //Paused
BOOST_CHECK_MESSAGE(p.get_state<State<by_name("Stopped")>&>().exit_counter == 1, "Playing exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<State<by_name("Paused")>&>().entry_counter == 1, "Paused entry not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<State<by_name("Stopped")>&>().exit_counter == 1, "Playing exit not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<State<by_name("Paused")>&>().entry_counter == 1, "Paused entry not called correctly");
// go back to Playing
p.process_event(Event<by_name("end_pause")>{});
BOOST_CHECK_MESSAGE(p.current_state()[0] == 3,"Playing should be active"); //Playing
BOOST_CHECK_MESSAGE(p.get_state<State<by_name("Paused")>&>().exit_counter == 1,"Paused exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<State<by_name("Playing")>&>().entry_counter == 2,"Playing entry not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<State<by_name("Paused")>&>().exit_counter == 1,"Paused exit not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<State<by_name("Playing")>&>().entry_counter == 2,"Playing entry not called correctly");
p.process_event(Event<by_name("pause")>{});
BOOST_CHECK_MESSAGE(p.current_state()[0] == 4,"Paused should be active"); //Paused
BOOST_CHECK_MESSAGE(p.get_state<State<by_name("Playing")>&>().exit_counter == 2,"Playing exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<State<by_name("Paused")>&>().entry_counter == 2,"Paused entry not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<State<by_name("Playing")>&>().exit_counter == 2,"Playing exit not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<State<by_name("Paused")>&>().entry_counter == 2,"Paused entry not called correctly");
p.process_event(Event<by_name("stop")>{});
BOOST_CHECK_MESSAGE(p.current_state()[0] == 0,"Stopped should be active"); //Stopped
BOOST_CHECK_MESSAGE(p.get_state<State<by_name("Paused")>&>().exit_counter == 2,"Paused exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<State<by_name("Stopped")>&>().entry_counter == 2,"Stopped entry not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<State<by_name("Paused")>&>().exit_counter == 2,"Paused exit not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<State<by_name("Stopped")>&>().entry_counter == 2,"Stopped entry not called correctly");
p.process_event(Event<by_name("stop")>{});
BOOST_CHECK_MESSAGE(p.current_state()[0] == 0,"Stopped should be active"); //Stopped
BOOST_CHECK_MESSAGE(p.get_state<State<by_name("Stopped")>&>().exit_counter == 2,"Stopped exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<State<by_name("Stopped")>&>().entry_counter == 3,"Stopped entry not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<State<by_name("Stopped")>&>().exit_counter == 2,"Stopped exit not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<State<by_name("Stopped")>&>().entry_counter == 3,"Stopped entry not called correctly");
}
}
+24 -24
View File
@@ -9,7 +9,7 @@
// http://www.boost.org/LICENSE_1_0.txt)
// back-end
#include <boost/msm/back/state_machine.hpp>
#include "BackCommon.hpp"
//front-end
#include <boost/msm/front/state_machine_def.hpp>
#ifndef BOOST_MSM_NONSTANDALONE_TEST
@@ -185,72 +185,72 @@ namespace
};
// Pick a back-end
typedef msm::back::state_machine<player_> player;
typedef get_test_machines<player_> players;
// static char const* const state_names[] = { "Stopped", "Open", "Empty", "Playing", "Paused" };
BOOST_AUTO_TEST_CASE( simple_machine_test )
BOOST_AUTO_TEST_CASE_TEMPLATE( simple_machine_test, player, players )
{
player p;
p.start();
BOOST_CHECK_MESSAGE(p.get_state<player_::Empty&>().entry_counter == 1,"Empty entry not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<player_::Empty&>().entry_counter == 1,"Empty entry not called correctly");
p.process_event(open_close());
BOOST_CHECK_MESSAGE(p.current_state()[0] == 1,"Open should be active"); //Open
BOOST_CHECK_MESSAGE(p.get_state<player_::Empty&>().exit_counter == 1,"Empty exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::Open&>().entry_counter == 1,"Open entry not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<player_::Empty&>().exit_counter == 1,"Empty exit not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<player_::Open&>().entry_counter == 1,"Open entry not called correctly");
p.process_event(open_close());
BOOST_CHECK_MESSAGE(p.current_state()[0] == 2,"Empty should be active"); //Empty
BOOST_CHECK_MESSAGE(p.get_state<player_::Open&>().exit_counter == 1,"Open exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::Empty&>().entry_counter == 2,"Empty entry not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<player_::Open&>().exit_counter == 1,"Open exit not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<player_::Empty&>().entry_counter == 2,"Empty entry not called correctly");
BOOST_CHECK_MESSAGE(p.can_close_drawer_counter == 1,"guard not called correctly");
p.process_event(
cd_detected("louie, louie",DISK_DVD));
BOOST_CHECK_MESSAGE(p.current_state()[0] == 2,"Empty should be active"); //Empty
BOOST_CHECK_MESSAGE(p.get_state<player_::Open&>().exit_counter == 1,"Open exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::Empty&>().entry_counter == 2,"Empty entry not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<player_::Open&>().exit_counter == 1,"Open exit not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<player_::Empty&>().entry_counter == 2,"Empty entry not called correctly");
p.process_event(
cd_detected("louie, louie",DISK_CD));
BOOST_CHECK_MESSAGE(p.current_state()[0] == 0,"Stopped should be active"); //Stopped
BOOST_CHECK_MESSAGE(p.get_state<player_::Empty&>().exit_counter == 2,"Empty exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::Stopped&>().entry_counter == 1,"Stopped entry not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<player_::Empty&>().exit_counter == 2,"Empty exit not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<player_::Stopped&>().entry_counter == 1,"Stopped entry not called correctly");
p.process_event(play());
BOOST_CHECK_MESSAGE(p.current_state()[0] == 3,"Playing should be active"); //Playing
BOOST_CHECK_MESSAGE(p.get_state<player_::Stopped&>().exit_counter == 1,"Stopped exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::Playing&>().entry_counter == 1,"Playing entry not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<player_::Stopped&>().exit_counter == 1,"Stopped exit not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<player_::Playing&>().entry_counter == 1,"Playing entry not called correctly");
BOOST_CHECK_MESSAGE(p.start_playback_counter == 1,"action not called correctly");
p.process_event(pause());
BOOST_CHECK_MESSAGE(p.current_state()[0] == 4,"Paused should be active"); //Paused
BOOST_CHECK_MESSAGE(p.get_state<player_::Playing&>().exit_counter == 1,"Playing exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::Paused&>().entry_counter == 1,"Paused entry not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<player_::Playing&>().exit_counter == 1,"Playing exit not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<player_::Paused&>().entry_counter == 1,"Paused entry not called correctly");
// go back to Playing
p.process_event(end_pause());
BOOST_CHECK_MESSAGE(p.current_state()[0] == 3,"Playing should be active"); //Playing
BOOST_CHECK_MESSAGE(p.get_state<player_::Paused&>().exit_counter == 1,"Paused exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::Playing&>().entry_counter == 2,"Playing entry not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<player_::Paused&>().exit_counter == 1,"Paused exit not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<player_::Playing&>().entry_counter == 2,"Playing entry not called correctly");
p.process_event(pause());
BOOST_CHECK_MESSAGE(p.current_state()[0] == 4,"Paused should be active"); //Paused
BOOST_CHECK_MESSAGE(p.get_state<player_::Playing&>().exit_counter == 2,"Playing exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::Paused&>().entry_counter == 2,"Paused entry not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<player_::Playing&>().exit_counter == 2,"Playing exit not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<player_::Paused&>().entry_counter == 2,"Paused entry not called correctly");
p.process_event(stop());
BOOST_CHECK_MESSAGE(p.current_state()[0] == 0,"Stopped should be active"); //Stopped
BOOST_CHECK_MESSAGE(p.get_state<player_::Paused&>().exit_counter == 2,"Paused exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::Stopped&>().entry_counter == 2,"Stopped entry not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<player_::Paused&>().exit_counter == 2,"Paused exit not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<player_::Stopped&>().entry_counter == 2,"Stopped entry not called correctly");
p.process_event(stop());
BOOST_CHECK_MESSAGE(p.current_state()[0] == 0,"Stopped should be active"); //Stopped
BOOST_CHECK_MESSAGE(p.get_state<player_::Stopped&>().exit_counter == 2,"Stopped exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::Stopped&>().entry_counter == 3,"Stopped entry not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<player_::Stopped&>().exit_counter == 2,"Stopped exit not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<player_::Stopped&>().entry_counter == 3,"Stopped entry not called correctly");
}
}
+40 -31
View File
@@ -9,7 +9,7 @@
// http://www.boost.org/LICENSE_1_0.txt)
// back-end
#include <boost/msm/back/state_machine.hpp>
#include "BackCommon.hpp"
//front-end
#include <boost/msm/front/state_machine_def.hpp>
// functors
@@ -18,7 +18,7 @@
#include <boost/msm/front/operator.hpp>
#ifndef BOOST_MSM_NONSTANDALONE_TEST
#define BOOST_TEST_MODULE SimpleWithFunctorsTest
#define BOOST_TEST_MODULE simple_with_functors_test
#endif
#include <boost/test/unit_test.hpp>
@@ -26,11 +26,12 @@ using namespace std;
namespace msm = boost::msm;
namespace mpl = boost::mpl;
using namespace msm::front;
namespace
{
// events
struct play {};
struct end_pause {};
struct play {int cpt_ = 0;};
struct end_pause {int cpt_ = 0;};
struct stop {};
struct pause {};
struct open_close {};
@@ -99,14 +100,18 @@ namespace
struct Playing : public msm::front::state<>
{
template <class Event,class FSM>
void on_entry(Event const&,FSM& ) {++entry_counter;}
void on_entry(Event const& e,FSM& )
{
++entry_counter;
event_counter = e.cpt_;
}
template <class Event,class FSM>
void on_exit(Event const&,FSM& ) {++exit_counter;}
int entry_counter;
int exit_counter;
int event_counter=0;
};
// state not defining any entry or exit
struct Paused : public msm::front::state<>
{
template <class Event,class FSM>
@@ -124,8 +129,9 @@ namespace
struct TestFct
{
template <class EVT,class FSM,class SourceState,class TargetState>
void operator()(EVT const&, FSM& fsm,SourceState& ,TargetState& )
void operator()(EVT& e, FSM& fsm,SourceState& ,TargetState& )
{
++e.cpt_;
++fsm.test_fct_counter;
}
};
@@ -176,8 +182,9 @@ namespace
struct resume_playback
{
template <class EVT,class FSM,class SourceState,class TargetState>
void operator()(EVT const& ,FSM& ,SourceState& ,TargetState& )
void operator()(EVT& e,FSM& ,SourceState& ,TargetState& )
{
++e.cpt_;
}
};
struct stop_and_open
@@ -287,70 +294,72 @@ namespace
};
// Pick a back-end
typedef msm::back::state_machine<player_> player;
typedef get_test_machines<player_> players;
// static char const* const state_names[] = { "Stopped", "Open", "Empty", "Playing", "Paused" };
BOOST_AUTO_TEST_CASE( SimpleWithFunctorsTest )
BOOST_AUTO_TEST_CASE_TEMPLATE( simple_with_functors_test, player, players )
{
player p;
p.start();
BOOST_CHECK_MESSAGE(p.get_state<player_::Empty&>().entry_counter == 1,"Empty entry not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<player_::Empty&>().entry_counter == 1,"Empty entry not called correctly");
p.process_event(open_close());
BOOST_CHECK_MESSAGE(p.current_state()[0] == 1,"Open should be active"); //Open
BOOST_CHECK_MESSAGE(p.get_state<player_::Empty&>().exit_counter == 1,"Empty exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::Open&>().entry_counter == 1,"Open entry not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<player_::Empty&>().exit_counter == 1,"Empty exit not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<player_::Open&>().entry_counter == 1,"Open entry not called correctly");
p.process_event(open_close());
BOOST_CHECK_MESSAGE(p.current_state()[0] == 2,"Empty should be active"); //Empty
BOOST_CHECK_MESSAGE(p.get_state<player_::Open&>().exit_counter == 1,"Open exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::Empty&>().entry_counter == 2,"Empty entry not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<player_::Open&>().exit_counter == 1,"Open exit not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<player_::Empty&>().entry_counter == 2,"Empty entry not called correctly");
BOOST_CHECK_MESSAGE(p.can_close_drawer_counter == 1,"guard not called correctly");
p.process_event(
cd_detected("louie, louie",DISK_DVD));
BOOST_CHECK_MESSAGE(p.current_state()[0] == 2,"Empty should be active"); //Empty
BOOST_CHECK_MESSAGE(p.get_state<player_::Open&>().exit_counter == 1,"Open exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::Empty&>().entry_counter == 2,"Empty entry not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<player_::Open&>().exit_counter == 1,"Open exit not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<player_::Empty&>().entry_counter == 2,"Empty entry not called correctly");
p.process_event(
cd_detected("louie, louie",DISK_CD));
BOOST_CHECK_MESSAGE(p.current_state()[0] == 3,"Playing should be active"); //Playing
BOOST_CHECK_MESSAGE(p.get_state<player_::Empty&>().exit_counter == 2,"Empty exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::Stopped&>().entry_counter == 1,"Stopped entry not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::Stopped&>().exit_counter == 1,"Stopped exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::Playing&>().entry_counter == 1,"Playing entry not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<player_::Empty&>().exit_counter == 2,"Empty exit not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<player_::Stopped&>().entry_counter == 1,"Stopped entry not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<player_::Stopped&>().exit_counter == 1,"Stopped exit not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<player_::Playing&>().entry_counter == 1,"Playing entry not called correctly");
BOOST_CHECK_MESSAGE(p.start_playback_counter == 1,"action not called correctly");
BOOST_CHECK_MESSAGE(p.test_fct_counter == 1,"action not called correctly");
p.process_event(pause());
BOOST_CHECK_MESSAGE(p.current_state()[0] == 4,"Paused should be active"); //Paused
BOOST_CHECK_MESSAGE(p.get_state<player_::Playing&>().exit_counter == 1,"Playing exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::Paused&>().entry_counter == 1,"Paused entry not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<player_::Playing&>().exit_counter == 1,"Playing exit not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<player_::Paused&>().entry_counter == 1,"Paused entry not called correctly");
// go back to Playing
p.process_event(end_pause());
BOOST_CHECK_MESSAGE(p.current_state()[0] == 3,"Playing should be active"); //Playing
BOOST_CHECK_MESSAGE(p.get_state<player_::Paused&>().exit_counter == 1,"Paused exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::Playing&>().entry_counter == 2,"Playing entry not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<player_::Paused&>().exit_counter == 1,"Paused exit not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<player_::Playing&>().entry_counter == 2,"Playing entry not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<player_::Playing&>().event_counter == 1,"Playing event counter incorrect");
p.process_event(pause());
BOOST_CHECK_MESSAGE(p.current_state()[0] == 4,"Paused should be active"); //Paused
BOOST_CHECK_MESSAGE(p.get_state<player_::Playing&>().exit_counter == 2,"Playing exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::Paused&>().entry_counter == 2,"Paused entry not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<player_::Playing&>().exit_counter == 2,"Playing exit not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<player_::Paused&>().entry_counter == 2,"Paused entry not called correctly");
p.process_event(stop());
BOOST_CHECK_MESSAGE(p.current_state()[0] == 0,"Stopped should be active"); //Stopped
BOOST_CHECK_MESSAGE(p.get_state<player_::Paused&>().exit_counter == 2,"Paused exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::Stopped&>().entry_counter == 2,"Stopped entry not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<player_::Paused&>().exit_counter == 2,"Paused exit not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<player_::Stopped&>().entry_counter == 2,"Stopped entry not called correctly");
p.process_event(stop());
BOOST_CHECK_MESSAGE(p.current_state()[0] == 0,"Stopped should be active"); //Stopped
BOOST_CHECK_MESSAGE(p.get_state<player_::Stopped&>().exit_counter == 2,"Stopped exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::Stopped&>().entry_counter == 3,"Stopped entry not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<player_::Stopped&>().exit_counter == 2,"Stopped exit not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<player_::Stopped&>().entry_counter == 3,"Stopped entry not called correctly");
}
}
@@ -10,14 +10,14 @@
// back-end
#include <boost/msm/back11/state_machine.hpp>
#include "BackCommon.hpp"
//front-end
#include <boost/msm/front/state_machine_def.hpp>
#include <boost/msm/front/puml/puml.hpp>
#include <PumlCommon.hpp>
#ifndef BOOST_MSM_NONSTANDALONE_TEST
#define BOOST_TEST_MODULE back11_simple_with_puml_test
#define BOOST_TEST_MODULE simple_with_puml_test
#endif
#include <boost/test/unit_test.hpp>
@@ -68,68 +68,68 @@ namespace
}
};
// Pick a back-end
typedef msm::back11::state_machine<player_> player;
typedef get_test_machines<player_> players;
BOOST_AUTO_TEST_CASE( back11_simple_with_puml_test )
BOOST_AUTO_TEST_CASE_TEMPLATE( simple_with_puml_test, player, players )
{
player p;
p.start();
BOOST_CHECK_MESSAGE(p.get_state<State<by_name("Empty")>&>().entry_counter == 1, "Empty entry not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<State<by_name("Empty")>&>().entry_counter == 1, "Empty entry not called correctly");
p.process_event(Event<by_name("open_close")>{});
BOOST_CHECK_MESSAGE(p.current_state()[0] == 1,"Open should be active"); //Open
BOOST_CHECK_MESSAGE(p.get_state<State<by_name("Empty")>&>().exit_counter == 1,"Empty exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<State<by_name("Open")>&>().entry_counter == 1,"Open entry not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<State<by_name("Empty")>&>().exit_counter == 1,"Empty exit not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<State<by_name("Open")>&>().entry_counter == 1,"Open entry not called correctly");
p.process_event(Event<by_name("open_close")>{});
BOOST_CHECK_MESSAGE(p.current_state()[0] == 2,"Empty should be active"); //Empty
BOOST_CHECK_MESSAGE(p.get_state<State<by_name("Open")>&>().exit_counter == 1,"Open exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<State<by_name("Empty")>&>().entry_counter == 2,"Empty entry not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<State<by_name("Open")>&>().exit_counter == 1,"Open exit not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<State<by_name("Empty")>&>().entry_counter == 2,"Empty entry not called correctly");
BOOST_CHECK_MESSAGE(p.can_close_drawer_counter == 1,"guard not called correctly");
p.process_event(Event<by_name("cd_detected")>{"louie, louie", DISK_DVD});
BOOST_CHECK_MESSAGE(p.current_state()[0] == 2,"Empty should be active"); //Empty
BOOST_CHECK_MESSAGE(p.get_state<State<by_name("Open")>&>().exit_counter == 1,"Open exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<State<by_name("Empty")>&>().entry_counter == 2,"Empty entry not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<State<by_name("Open")>&>().exit_counter == 1,"Open exit not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<State<by_name("Empty")>&>().entry_counter == 2,"Empty entry not called correctly");
p.process_event(Event<by_name("cd_detected")>{"louie, louie", DISK_CD});
BOOST_CHECK_MESSAGE(p.current_state()[0] == 3,"Playing2 should be active"); //Playing2
BOOST_CHECK_MESSAGE(p.get_state<State<by_name("Empty")>&>().exit_counter == 2,"Empty exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<State<by_name("Stopped")>&>().entry_counter == 1,"Stopped entry not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<State<by_name("Stopped")>&>().exit_counter == 1,"Stopped exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<State<by_name("Playing2")>&>().entry_counter == 1,"Playing2 entry not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<State<by_name("Empty")>&>().exit_counter == 2,"Empty exit not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<State<by_name("Stopped")>&>().entry_counter == 1,"Stopped entry not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<State<by_name("Stopped")>&>().exit_counter == 1,"Stopped exit not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<State<by_name("Playing2")>&>().entry_counter == 1,"Playing2 entry not called correctly");
BOOST_CHECK_MESSAGE(p.start_playback_counter == 1,"action not called correctly");
BOOST_CHECK_MESSAGE(p.test_fct_counter == 1,"action not called correctly");
p.process_event(Event<by_name("pause")>{});
BOOST_CHECK_MESSAGE(p.current_state()[0] == 4,"Paused should be active"); //Paused
BOOST_CHECK_MESSAGE(p.get_state<State<by_name("Playing2")>&>().exit_counter == 1,"Playing2 exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<State<by_name("Paused")>&>().entry_counter == 1,"Paused entry not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<State<by_name("Playing2")>&>().exit_counter == 1,"Playing2 exit not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<State<by_name("Paused")>&>().entry_counter == 1,"Paused entry not called correctly");
// go back to Playing2
p.process_event(Event<by_name("end_pause")>{});
BOOST_CHECK_MESSAGE(p.current_state()[0] == 3,"Playing2 should be active"); //Playing2
BOOST_CHECK_MESSAGE(p.get_state<State<by_name("Paused")>&>().exit_counter == 1,"Paused exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<State<by_name("Playing2")>&>().entry_counter == 2,"Playing2 entry not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<State<by_name("Playing2")>&>().event_counter == 1,"Playing2 event counter incorrect");
BOOST_CHECK_MESSAGE(p.template get_state<State<by_name("Paused")>&>().exit_counter == 1,"Paused exit not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<State<by_name("Playing2")>&>().entry_counter == 2,"Playing2 entry not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<State<by_name("Playing2")>&>().event_counter == 1,"Playing2 event counter incorrect");
p.process_event(Event<by_name("pause")>{});
BOOST_CHECK_MESSAGE(p.current_state()[0] == 4,"Paused should be active"); //Paused
BOOST_CHECK_MESSAGE(p.get_state<State<by_name("Playing2")>&>().exit_counter == 2,"Playing2 exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<State<by_name("Paused")>&>().entry_counter == 2,"Paused entry not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<State<by_name("Playing2")>&>().exit_counter == 2,"Playing2 exit not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<State<by_name("Paused")>&>().entry_counter == 2,"Paused entry not called correctly");
p.process_event(Event<by_name("stop")>{});
BOOST_CHECK_MESSAGE(p.current_state()[0] == 0,"Stopped should be active"); //Stopped
BOOST_CHECK_MESSAGE(p.get_state<State<by_name("Paused")>&>().exit_counter == 2,"Paused exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<State<by_name("Stopped")>&>().entry_counter == 2,"Stopped entry not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<State<by_name("Paused")>&>().exit_counter == 2,"Paused exit not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<State<by_name("Stopped")>&>().entry_counter == 2,"Stopped entry not called correctly");
p.process_event(Event<by_name("stop")>{});
BOOST_CHECK_MESSAGE(p.current_state()[0] == 0,"Stopped should be active"); //Stopped
BOOST_CHECK_MESSAGE(p.get_state<State<by_name("Stopped")>&>().exit_counter == 2,"Stopped exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<State<by_name("Stopped")>&>().entry_counter == 3,"Stopped entry not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<State<by_name("Stopped")>&>().exit_counter == 2,"Stopped exit not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<State<by_name("Stopped")>&>().entry_counter == 3,"Stopped entry not called correctly");
}
}
@@ -10,14 +10,14 @@
// back-end
#include <boost/msm/back11/state_machine.hpp>
#include "BackCommon.hpp"
//front-end
#include <boost/msm/front/state_machine_def.hpp>
#include <boost/msm/front/puml/puml.hpp>
#include <PumlCommon.hpp>
#ifndef BOOST_MSM_NONSTANDALONE_TEST
#define BOOST_TEST_MODULE back11_only_string_puml_test
#define BOOST_TEST_MODULE string_terminate_puml_test
#endif
#include <boost/test/unit_test.hpp>
@@ -58,10 +58,10 @@ namespace
}
};
// Pick a back-end
typedef msm::back11::state_machine<front_> machine;
typedef get_test_machines<front_> machines;
BOOST_AUTO_TEST_CASE(back11_string_terminate_puml_test)
BOOST_AUTO_TEST_CASE_TEMPLATE(string_terminate_puml_test, machine, machines)
{
machine p;
static_assert(msm::back11::get_number_of_regions<typename machine::initial_state>::type::value == 2);
+16 -13
View File
@@ -9,7 +9,7 @@
// http://www.boost.org/LICENSE_1_0.txt)
// back-end
#include <boost/msm/back/state_machine.hpp>
#include "BackCommon.hpp"
//front-end
#include <boost/msm/front/state_machine_def.hpp>
// functors
@@ -18,6 +18,9 @@
// for And_ operator
#include <boost/msm/front/euml/operator.hpp>
#ifndef BOOST_MSM_NONSTANDALONE_TEST
#define BOOST_TEST_MODULE test_2_regions_anonymous
#endif
#include <boost/test/unit_test.hpp>
using namespace std;
@@ -139,9 +142,9 @@ namespace
}
};
// Pick a back-end
typedef msm::back::state_machine<my_machine_> my_machine;
typedef get_test_machines<my_machine_> my_machines;
BOOST_AUTO_TEST_CASE( my_test )
BOOST_AUTO_TEST_CASE_TEMPLATE( test_2_regions_anonymous, my_machine, my_machines )
{
my_machine p;
@@ -153,16 +156,16 @@ namespace
BOOST_CHECK_MESSAGE(p.current_state()[0] == 3,"State3 should be active");
BOOST_CHECK_MESSAGE(p.current_state()[1] == 2,"State1b should be active");
BOOST_CHECK_MESSAGE(p.get_state<my_machine_::State1&>().exit_counter == 1,"State1 exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<my_machine_::State1&>().entry_counter == 1,"State1 entry not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<my_machine_::State2&>().exit_counter == 1,"State2 exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<my_machine_::State2&>().entry_counter == 1,"State2 entry not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<my_machine_::State3&>().exit_counter == 0,"State3 exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<my_machine_::State3&>().entry_counter == 1,"State3 entry not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<my_machine_::State1b&>().entry_counter == 1,"State1b entry not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<my_machine_::State1b&>().exit_counter == 0,"State1b exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<my_machine_::State2b&>().entry_counter == 0,"State2b entry not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<my_machine_::State2b&>().exit_counter == 0,"State2b exit not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<my_machine_::State1&>().exit_counter == 1,"State1 exit not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<my_machine_::State1&>().entry_counter == 1,"State1 entry not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<my_machine_::State2&>().exit_counter == 1,"State2 exit not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<my_machine_::State2&>().entry_counter == 1,"State2 entry not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<my_machine_::State3&>().exit_counter == 0,"State3 exit not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<my_machine_::State3&>().entry_counter == 1,"State3 entry not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<my_machine_::State1b&>().entry_counter == 1,"State1b entry not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<my_machine_::State1b&>().exit_counter == 0,"State1b exit not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<my_machine_::State2b&>().entry_counter == 0,"State2b entry not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<my_machine_::State2b&>().exit_counter == 0,"State2b exit not called correctly");
}
+33 -16
View File
@@ -9,11 +9,11 @@
// http://www.boost.org/LICENSE_1_0.txt)
// back-end
#include <boost/msm/back/state_machine.hpp>
#include "BackCommon.hpp"
//front-end
#include <boost/msm/front/state_machine_def.hpp>
#ifndef BOOST_MSM_NONSTANDALONE_TEST
#define BOOST_TEST_MODULE MyTest
#define BOOST_TEST_MODULE test_constructor
#endif
#include <boost/test/unit_test.hpp>
#include <boost/config.hpp>
@@ -55,9 +55,14 @@ namespace
DiskTypeEnum disc_type;
};
template<template <typename...> class Back, typename Policy = void>
struct hierarchical_state_machine
{
// front-end: define the FSM structure
struct player_ : public msm::front::state_machine_def<player_>
{
BOOST_MSM_TEST_DEFINE_DEPENDENT_TEMPLATES(player_);
player_(SomeExternalContext& context,int someint)
:context_(context)
{
@@ -108,6 +113,8 @@ namespace
struct Playing_ : public msm::front::state_machine_def<Playing_>
{
BOOST_MSM_TEST_DEFINE_DEPENDENT_TEMPLATES(Playing_);
// when playing, the CD is loaded and we are in either pause or playing (duh)
template <class Event,class FSM>
void on_entry(Event const&,FSM& ) {std::cout << "entering: Playing" << std::endl;}
@@ -168,7 +175,7 @@ namespace
}
};
// back-end
typedef msm::back::state_machine<Playing_> Playing;
typedef Back<Playing_, Policy> Playing;
// state not defining any entry or exit
struct Paused : public msm::front::state<>
@@ -238,26 +245,36 @@ namespace
BOOST_FAIL("no_transition called!");
}
};
typedef Back<player_, Policy> player;
};
// Pick a back-end
typedef msm::back::state_machine<player_> player;
// typedef msm::back::state_machine<player_> player;
typedef boost::mpl::vector<
hierarchical_state_machine<boost::msm::back::state_machine>,
hierarchical_state_machine<boost::msm::back::state_machine, boost::msm::back::favor_compile_time>,
hierarchical_state_machine<boost::msm::back11::state_machine>
> test_machines;
BOOST_AUTO_TEST_CASE( my_test )
{
BOOST_AUTO_TEST_CASE_TEMPLATE( test_constructor, test_machine, test_machines )
{
typedef typename test_machine::player player;
typedef typename test_machine::player_ player_;
SomeExternalContext ctx(3);
player p1(boost::ref(ctx),5);
BOOST_CHECK_MESSAGE(p1.context_.bla == 10,"Wrong returned context value");
ctx.bla = 3;
player p2(msm::back::states_ << player_::Empty(1),boost::ref(ctx),5);
BOOST_CHECK_MESSAGE(p2.get_state<player_::Empty&>().data_ == 1,"Wrong Empty value");
player p2(msm::back::states_ << typename player_::Empty(1),boost::ref(ctx),5);
BOOST_CHECK_MESSAGE(p2.template get_state<typename player_::Empty&>().data_ == 1,"Wrong Empty value");
p2.set_states(msm::back::states_ << player_::Empty(5));
BOOST_CHECK_MESSAGE(p2.get_state<player_::Empty&>().data_ == 5,"Wrong Empty value");
p2.set_states(msm::back::states_ << typename player_::Empty(5));
BOOST_CHECK_MESSAGE(p2.template get_state<typename player_::Empty&>().data_ == 5,"Wrong Empty value");
p2.set_states(msm::back::states_ << player_::Empty(7) << player_::Open(2));
BOOST_CHECK_MESSAGE(p2.get_state<player_::Empty&>().data_ == 7,"Wrong Empty value");
BOOST_CHECK_MESSAGE(p2.get_state<player_::Open&>().data_ == 2,"Wrong Open value");
p2.set_states(msm::back::states_ << typename player_::Empty(7) << typename player_::Open(2));
BOOST_CHECK_MESSAGE(p2.template get_state<typename player_::Empty&>().data_ == 7,"Wrong Empty value");
BOOST_CHECK_MESSAGE(p2.template get_state<typename player_::Open&>().data_ == 2,"Wrong Open value");
#if defined(BOOST_MSVC) && BOOST_MSVC >= 1910 && BOOST_MSVC < 1930
@@ -270,10 +287,10 @@ namespace
#else
ctx.bla = 3;
player p(msm::back::states_ << player_::Empty(1)
<< player_::Playing(msm::back::states_ << player_::Playing_::Song1(8)),
player p(msm::back::states_ << typename player_::Empty(1)
<< typename player_::Playing(msm::back::states_ << typename player_::Playing_::Song1(8)),
boost::ref(ctx),5);
BOOST_CHECK_MESSAGE(p.get_state<player_::Playing&>().get_state<player_::Playing_::Song1&>().data_ == 8,"Wrong Open value");
BOOST_CHECK_MESSAGE(p.template get_state<typename player_::Playing&>().template get_state<typename player_::Playing_::Song1&>().data_ == 8,"Wrong Open value");
#endif
}
+4 -4
View File
@@ -15,11 +15,11 @@
#include <memory>
// back-end
#include <boost/msm/back/state_machine.hpp>
#include "BackCommon.hpp"
//front-end
#include <boost/msm/front/state_machine_def.hpp>
#ifndef BOOST_MSM_NONSTANDALONE_TEST
#define BOOST_TEST_MODULE MyTest
#define BOOST_TEST_MODULE test_constructor_movable_only_types
#endif
#include <boost/test/unit_test.hpp>
@@ -94,9 +94,9 @@ namespace
};
// Pick a back-end
typedef msm::back::state_machine<bistable_switch_> bistable_switch;
typedef get_test_machines<bistable_switch_> bistable_switches;
BOOST_AUTO_TEST_CASE(my_test)
BOOST_AUTO_TEST_CASE_TEMPLATE(test_constructor_movable_only_types, bistable_switch, bistable_switches)
{
auto bulp = std::make_unique<Lightbulp>(3);
+13 -10
View File
@@ -9,11 +9,14 @@
// http://www.boost.org/LICENSE_1_0.txt)
// back-end
#include <boost/msm/back/state_machine.hpp>
#include "BackCommon.hpp"
//front-end
#include <boost/msm/front/state_machine_def.hpp>
#include <boost/msm/front/functor_row.hpp>
#ifndef BOOST_MSM_NONSTANDALONE_TEST
#define BOOST_TEST_MODULE test_defer_and_message_queue
#endif
#include <boost/test/unit_test.hpp>
namespace msm = boost::msm;
@@ -162,9 +165,9 @@ namespace
int expected_action_counter;
};
// Pick a back-end
typedef msm::back::state_machine<player_> player;
typedef get_test_machines<player_> players;
BOOST_AUTO_TEST_CASE( TestDeferAndMessageQueue )
BOOST_AUTO_TEST_CASE_TEMPLATE( test_defer_and_message_queue, player, players )
{
player p;
// needed to start the highest-level SM. This will call on_entry and mark the start of the SM
@@ -173,17 +176,17 @@ namespace
p.process_event(eventConnect());
BOOST_CHECK_MESSAGE(p.current_state()[0] == 1,"Resolving should be active");
BOOST_CHECK_MESSAGE(p.current_state()[1] == 3,"State22 should be active");
BOOST_CHECK_MESSAGE(p.get_state<player_::Unresolved&>().exit_counter == 1,"Unresolved exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::Unresolved&>().entry_counter == 1,"Unresolved entry not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::Resolving&>().entry_counter == 1,"Resolving entry not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<player_::Unresolved&>().exit_counter == 1,"Unresolved exit not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<player_::Unresolved&>().entry_counter == 1,"Unresolved entry not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<player_::Resolving&>().entry_counter == 1,"Resolving entry not called correctly");
p.process_event(eventResolved());
BOOST_CHECK_MESSAGE(p.current_state()[0] == 4,"Connecting should be active");
BOOST_CHECK_MESSAGE(p.current_state()[1] == 3,"State22 should be active");
BOOST_CHECK_MESSAGE(p.get_state<player_::Resolved&>().exit_counter == 1,"Resolved exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::Resolved&>().entry_counter == 1,"Resolved entry not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::Resolving&>().exit_counter == 1,"Resolving exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::Connecting&>().entry_counter == 1,"Connecting entry not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<player_::Resolved&>().exit_counter == 1,"Resolved exit not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<player_::Resolved&>().entry_counter == 1,"Resolved entry not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<player_::Resolving&>().exit_counter == 1,"Resolving exit not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<player_::Connecting&>().entry_counter == 1,"Connecting entry not called correctly");
BOOST_CHECK_MESSAGE(p.expected_action_counter == 1,"expected_action should have been called");
+13 -10
View File
@@ -9,11 +9,14 @@
// http://www.boost.org/LICENSE_1_0.txt)
// back-end
#include <boost/msm/back/state_machine.hpp>
#include "BackCommon.hpp"
//front-end
#include <boost/msm/front/state_machine_def.hpp>
#include <boost/msm/front/functor_row.hpp>
#ifndef BOOST_MSM_NONSTANDALONE_TEST
#define BOOST_TEST_MODULE test_defer_and_message_queue_2
#endif
#include <boost/test/unit_test.hpp>
namespace msm = boost::msm;
@@ -126,9 +129,9 @@ namespace
int expected_action2_counter;
};
// Pick a back-end
typedef msm::back::state_machine<player_> player;
typedef get_test_machines<player_> players;
BOOST_AUTO_TEST_CASE( TestDeferAndMessageQueue2 )
BOOST_AUTO_TEST_CASE_TEMPLATE( test_defer_and_message_queue_2, player, players )
{
player p;
// needed to start the highest-level SM. This will call on_entry and mark the start of the SM
@@ -136,16 +139,16 @@ namespace
p.process_event(eventd());
BOOST_CHECK_MESSAGE(p.current_state()[0] == 0,"State11 should be active");
BOOST_CHECK_MESSAGE(p.get_state<player_::State11&>().entry_counter == 1,"State11 entry not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<player_::State11&>().entry_counter == 1,"State11 entry not called correctly");
p.process_event(event1());
BOOST_CHECK_MESSAGE(p.current_state()[0] == 0,"State11 should be active");
BOOST_CHECK_MESSAGE(p.get_state<player_::State11&>().exit_counter == 1,"State11 exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::State12&>().entry_counter == 1,"State12 entry not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::State12&>().exit_counter == 1,"State12 exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::State11&>().entry_counter == 2,"State11 entry not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::State13&>().exit_counter == 1,"State13 exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::State13&>().entry_counter == 1,"State13 entry not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<player_::State11&>().exit_counter == 1,"State11 exit not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<player_::State12&>().entry_counter == 1,"State12 entry not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<player_::State12&>().exit_counter == 1,"State12 exit not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<player_::State11&>().entry_counter == 2,"State11 entry not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<player_::State13&>().exit_counter == 1,"State13 exit not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<player_::State13&>().entry_counter == 1,"State13 entry not called correctly");
BOOST_CHECK_MESSAGE(p.expected_action_counter == 1,"expected_action should have been called");
BOOST_CHECK_MESSAGE(p.expected_action2_counter == 0,"expected_action2 should not have been called");
}
+13 -10
View File
@@ -9,11 +9,14 @@
// http://www.boost.org/LICENSE_1_0.txt)
// back-end
#include <boost/msm/back/state_machine.hpp>
#include "BackCommon.hpp"
//front-end
#include <boost/msm/front/state_machine_def.hpp>
#include <boost/msm/front/functor_row.hpp>
#ifndef BOOST_MSM_NONSTANDALONE_TEST
#define BOOST_TEST_MODULE test_defer_and_message_queue_3
#endif
#include <boost/test/unit_test.hpp>
namespace msm = boost::msm;
@@ -129,9 +132,9 @@ namespace
int expected_action2_counter;
};
// Pick a back-end
typedef msm::back::state_machine<player_> player;
typedef get_test_machines<player_> players;
BOOST_AUTO_TEST_CASE( TestDeferAndMessageQueue2 )
BOOST_AUTO_TEST_CASE_TEMPLATE( test_defer_and_message_queue_3, player, players )
{
player p;
// needed to start the highest-level SM. This will call on_entry and mark the start of the SM
@@ -139,16 +142,16 @@ namespace
p.process_event(eventd());
BOOST_CHECK_MESSAGE(p.current_state()[0] == 0,"State11 should be active");
BOOST_CHECK_MESSAGE(p.get_state<player_::State11&>().entry_counter == 1,"State11 entry not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<player_::State11&>().entry_counter == 1,"State11 entry not called correctly");
p.process_event(event1());
BOOST_CHECK_MESSAGE(p.current_state()[0] == 0,"State11 should be active");
BOOST_CHECK_MESSAGE(p.get_state<player_::State11&>().exit_counter == 1,"State11 exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::State12&>().entry_counter == 1,"State12 entry not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::State12&>().exit_counter == 1,"State12 exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::State11&>().entry_counter == 2,"State11 entry not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::State13&>().exit_counter == 1,"State13 exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::State13&>().entry_counter == 1,"State13 entry not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<player_::State11&>().exit_counter == 1,"State11 exit not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<player_::State12&>().entry_counter == 1,"State12 entry not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<player_::State12&>().exit_counter == 1,"State12 exit not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<player_::State11&>().entry_counter == 2,"State11 entry not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<player_::State13&>().exit_counter == 1,"State13 exit not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<player_::State13&>().entry_counter == 1,"State13 entry not called correctly");
BOOST_CHECK_MESSAGE(p.expected_action_counter == 0,"expected_action should have been called");
BOOST_CHECK_MESSAGE(p.expected_action2_counter == 1,"expected_action2 should not have been called");
}
+28 -26
View File
@@ -9,11 +9,13 @@
// http://www.boost.org/LICENSE_1_0.txt)
// back-end
#include <boost/msm/back/state_machine.hpp>
#include "BackCommon.hpp"
//front-end
#include <boost/msm/front/state_machine_def.hpp>
#include <boost/msm/front/functor_row.hpp>
#ifndef BOOST_MSM_NONSTANDALONE_TEST
#define BOOST_TEST_MODULE Back11TestDeferIn2Regions
#endif
#include <boost/test/unit_test.hpp>
namespace msm = boost::msm;
@@ -44,7 +46,7 @@ namespace
};
struct State12 : public msm::front::state<>
{
typedef mpl::vector<eventd> deferred_events;
typedef boost::fusion::vector<eventd> deferred_events;
template <class Event,class FSM>
void on_entry(Event const&,FSM& ) {++entry_counter;}
template <class Event,class FSM>
@@ -80,11 +82,11 @@ namespace
int exit_counter;
};
// the initial state of the player SM. Must be defined
typedef mpl::vector<State11,State21> initial_state;
typedef boost::fusion::vector<State11,State21> initial_state;
// Transition table for player
struct transition_table : mpl::vector<
struct transition_table : boost::fusion::vector<
// Start Event Next Action Guard
// +---------+-------------+---------+---------------------+----------------------+
Row < State11 , event1 , State12 >,
@@ -116,9 +118,9 @@ namespace
}
};
// Pick a back-end
typedef msm::back::state_machine<player_> player;
typedef get_test_machines<player_> players;
BOOST_AUTO_TEST_CASE( TestDeferIn2Regions )
BOOST_AUTO_TEST_CASE_TEMPLATE( Back11TestDeferIn2Regions, player, players )
{
player p;
// needed to start the highest-level SM. This will call on_entry and mark the start of the SM
@@ -127,40 +129,40 @@ namespace
p.process_event(event1());
BOOST_CHECK_MESSAGE(p.current_state()[0] == 1,"State12 should be active");
BOOST_CHECK_MESSAGE(p.current_state()[1] == 2,"State21 should be active");
BOOST_CHECK_MESSAGE(p.get_state<player_::State11&>().exit_counter == 1,"State11 exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::State11&>().entry_counter == 1,"State11 entry not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::State12&>().entry_counter == 1,"State12 entry not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<player_::State11&>().exit_counter == 1,"State11 exit not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<player_::State11&>().entry_counter == 1,"State11 entry not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<player_::State12&>().entry_counter == 1,"State12 entry not called correctly");
// deferred
p.process_event(eventd());
BOOST_CHECK_MESSAGE(p.current_state()[0] == 1,"State12 should be active");
BOOST_CHECK_MESSAGE(p.current_state()[1] == 2,"State21 should be active");
BOOST_CHECK_MESSAGE(p.get_state<player_::State11&>().exit_counter == 1,"State11 exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::State11&>().entry_counter == 1,"State11 entry not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::State12&>().entry_counter == 1,"State12 entry not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::State12&>().exit_counter == 0,"State12 exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::State21&>().exit_counter == 0,"State21 exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::State21&>().entry_counter == 1,"State21 entry not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::State22&>().exit_counter == 0,"State22 exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::State22&>().entry_counter == 0,"State22 entry not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<player_::State11&>().exit_counter == 1,"State11 exit not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<player_::State11&>().entry_counter == 1,"State11 entry not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<player_::State12&>().entry_counter == 1,"State12 entry not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<player_::State12&>().exit_counter == 0,"State12 exit not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<player_::State21&>().exit_counter == 0,"State21 exit not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<player_::State21&>().entry_counter == 1,"State21 entry not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<player_::State22&>().exit_counter == 0,"State22 exit not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<player_::State22&>().entry_counter == 0,"State22 entry not called correctly");
p.process_event(event3());
BOOST_CHECK_MESSAGE(p.current_state()[0] == 1,"State12 should be active");
BOOST_CHECK_MESSAGE(p.current_state()[1] == 2,"State21 should be active");
BOOST_CHECK_MESSAGE(p.get_state<player_::State21&>().exit_counter == 1,"State21 exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::State21&>().entry_counter == 2,"State21 entry not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::State22&>().exit_counter == 1,"State22 exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::State22&>().entry_counter == 1,"State22 entry not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<player_::State21&>().exit_counter == 1,"State21 exit not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<player_::State21&>().entry_counter == 2,"State21 entry not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<player_::State22&>().exit_counter == 1,"State22 exit not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<player_::State22&>().entry_counter == 1,"State22 entry not called correctly");
BOOST_CHECK_MESSAGE(p.get_deferred_queue().size() == 1,"Deferred queue should have one element");
p.clear_deferred_queue();
p.process_event(event2());
BOOST_CHECK_MESSAGE(p.current_state()[0] == 4,"State13 should be active");
BOOST_CHECK_MESSAGE(p.current_state()[1] == 2,"State21 should be active");
BOOST_CHECK_MESSAGE(p.get_state<player_::State21&>().exit_counter == 1,"State21 exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::State21&>().entry_counter == 2,"State21 entry not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::State22&>().exit_counter == 1,"State22 exit not called correctly");
BOOST_CHECK_MESSAGE(p.get_state<player_::State22&>().entry_counter == 1,"State22 entry not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<player_::State21&>().exit_counter == 1,"State21 exit not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<player_::State21&>().entry_counter == 2,"State21 entry not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<player_::State22&>().exit_counter == 1,"State22 exit not called correctly");
BOOST_CHECK_MESSAGE(p.template get_state<player_::State22&>().entry_counter == 1,"State22 entry not called correctly");
BOOST_CHECK_MESSAGE(p.get_deferred_queue().size() == 0,"Deferred queue should have no element");
}
}
+12 -12
View File
@@ -9,7 +9,7 @@
// http://www.boost.org/LICENSE_1_0.txt)
// back-end
#include <boost/msm/back11/state_machine.hpp>
#include "BackCommon.hpp"
//front-end
#include <boost/msm/front/state_machine_def.hpp>
#include <boost/msm/front/functor_row.hpp>
@@ -17,7 +17,7 @@
#include <iostream>
#ifndef BOOST_MSM_NONSTANDALONE_TEST
#define BOOST_TEST_MODULE Back11ThrowingTest
#define BOOST_TEST_MODULE throwing_test
#endif
#include <boost/test/unit_test.hpp>
@@ -113,23 +113,23 @@ namespace
}
};
using MyMachine = boost::msm::back11::state_machine<MyMachineFrontend>;
using MyMachines = get_test_machines<MyMachineFrontend>;
BOOST_AUTO_TEST_CASE(Back11ThrowingTest)
BOOST_AUTO_TEST_CASE_TEMPLATE(throwing_test, MyMachine, MyMachines)
{
MyMachine m;
m.start();
BOOST_CHECK_MESSAGE(m.get_state<Init&>().entry_counter == 1, "Init entry not called correctly");
BOOST_CHECK_MESSAGE(m.get_state<Init&>().exit_counter == 1, "Init exit not called correctly");
BOOST_CHECK_MESSAGE(m.get_state<Intermediate&>().entry_counter == 0, "Intermediate entry not called correctly");
BOOST_CHECK_MESSAGE(m.get_state<Intermediate&>().exit_counter == 0, "Intermediate exit not called correctly");
BOOST_CHECK_MESSAGE(m.template get_state<Init&>().entry_counter == 1, "Init entry not called correctly");
BOOST_CHECK_MESSAGE(m.template get_state<Init&>().exit_counter == 1, "Init exit not called correctly");
BOOST_CHECK_MESSAGE(m.template get_state<Intermediate&>().entry_counter == 0, "Intermediate entry not called correctly");
BOOST_CHECK_MESSAGE(m.template get_state<Intermediate&>().exit_counter == 0, "Intermediate exit not called correctly");
BOOST_CHECK_MESSAGE(m.get_state<WaitingForException&>().entry_counter == 1, "WaitingForException entry not called correctly");
BOOST_CHECK_MESSAGE(m.get_state<WaitingForException&>().exit_counter == 1, "WaitingForException exit not called correctly");
BOOST_CHECK_MESSAGE(m.get_state<End&>().entry_counter == 1, "End entry not called correctly");
BOOST_CHECK_MESSAGE(m.get_state<End&>().exit_counter == 0, "End exit not called correctly");
BOOST_CHECK_MESSAGE(m.template get_state<WaitingForException&>().entry_counter == 1, "WaitingForException entry not called correctly");
BOOST_CHECK_MESSAGE(m.template get_state<WaitingForException&>().exit_counter == 1, "WaitingForException exit not called correctly");
BOOST_CHECK_MESSAGE(m.template get_state<End&>().entry_counter == 1, "End entry not called correctly");
BOOST_CHECK_MESSAGE(m.template get_state<End&>().exit_counter == 0, "End exit not called correctly");
BOOST_CHECK_MESSAGE(m.current_state()[0] == 0, "Init should be active");
@@ -11,20 +11,11 @@
#include <iostream>
#ifndef BOOST_MSM_NONSTANDALONE_TEST
#define BOOST_TEST_MODULE back11_transition_skipping
#define BOOST_TEST_MODULE transition_skipping_test
#endif
#include <boost/test/unit_test.hpp>
#include <boost/core/demangle.hpp>
//#define USE_PRE11_MSM_BACKEND // <- toggle this to switch between back vs back11
// back-end
#if defined(USE_PRE11_MSM_BACKEND)
#include <boost/msm/back/state_machine.hpp>
namespace msm_back = boost::msm::back;
#else
#include <boost/msm/back11/state_machine.hpp>
namespace msm_back = boost::msm::back11;
#endif
#include "BackCommon.hpp"
// front-end
#include <boost/fusion/include/insert_range.hpp>
@@ -135,26 +126,26 @@ struct top_ : public msmf::state_machine_def<top_> {
>;
};
using top = msm_back::state_machine<top_>;
using tops = get_test_machines<top_>;
BOOST_AUTO_TEST_CASE(back11_transition_skipping)
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.get_state<top_::nested&>().exit_counter == 1, "nested exit not called correctly");
BOOST_CHECK_MESSAGE(msm.get_state<top_::nested&>().entry_counter == 1, "nested entry not called correctly");
BOOST_CHECK_MESSAGE(msm.get_state<top_::other2&>().exit_counter == 0, "other2 exit not called correctly");
BOOST_CHECK_MESSAGE(msm.get_state<top_::other2&>().entry_counter == 1, "other2 entry not called correctly");
BOOST_CHECK_MESSAGE(msm.get_state<top_::other1&>().exit_counter == 0, "other1 exit not called correctly");
BOOST_CHECK_MESSAGE(msm.get_state<top_::other1&>().entry_counter == 0, "other1 entry not called correctly");
BOOST_CHECK_MESSAGE(msm.get_state<top_::other3&>().exit_counter == 0, "other3 exit not called correctly");
BOOST_CHECK_MESSAGE(msm.get_state<top_::other3&>().entry_counter == 0, "other3 entry not called correctly");
BOOST_CHECK_MESSAGE(msm.get_state<top_::other4&>().exit_counter == 0, "other4 exit not called correctly");
BOOST_CHECK_MESSAGE(msm.get_state<top_::other4&>().entry_counter == 0, "other4 entry not called correctly");
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
}