File: KleeneDeferred.cpp

package info (click to toggle)
boost1.90 1.90.0-1
  • links: PTS, VCS
  • area: main
  • in suites:
  • size: 593,120 kB
  • sloc: cpp: 4,190,908; xml: 196,648; python: 34,618; ansic: 23,145; asm: 5,468; sh: 3,774; makefile: 1,161; perl: 1,020; sql: 728; ruby: 676; yacc: 478; java: 77; lisp: 24; csh: 6
file content (132 lines) | stat: -rw-r--r-- 5,230 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
// 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 "BackCommon.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 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 mpl::vector<
#ifndef BOOST_MSM_TEST_SKIP_BACKMP11
        boost::msm::backmp11::state_machine_adapter<fsm_>,
#endif // BOOST_MSM_TEST_SKIP_BACKMP11
        boost::msm::back::state_machine<fsm_>,
        boost::msm::back11::state_machine<fsm_>
        > Fsms;

    BOOST_AUTO_TEST_CASE_TEMPLATE(kleene_deferred_test, Fsm, Fsms)
    {     
        Fsm fsm;

        fsm.start(); 
        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.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.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.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");

    }
}