1 //////////////////////////////////////////////////////////////////////////////
2 // Copyright 2005-2006 Andreas Huber Doenni
3 // Distributed under the Boost Software License, Version 1.0. (See accompany-
4 // ing file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
5 //////////////////////////////////////////////////////////////////////////////
6 
7 
8 
9 #include <boost/statechart/state_machine.hpp>
10 #include <boost/statechart/event.hpp>
11 #include <boost/statechart/simple_state.hpp>
12 #include <boost/statechart/state.hpp>
13 #include <boost/statechart/transition.hpp>
14 #include <boost/statechart/custom_reaction.hpp>
15 
16 #include <boost/mpl/list.hpp>
17 #include <boost/intrusive_ptr.hpp>
18 
19 #include <boost/test/test_tools.hpp>
20 
21 
22 
23 namespace sc = boost::statechart;
24 namespace mpl = boost::mpl;
25 
26 
27 
28 struct EvToB : sc::event< EvToB > {};
29 struct EvToF : sc::event< EvToF > {};
30 struct EvCheck : sc::event< EvCheck > {};
31 
32 struct A;
33 struct StateCastTest : sc::state_machine< StateCastTest, A >
34 {
35   template< class State >
AssertInStateStateCastTest36   void AssertInState()
37   {
38     BOOST_REQUIRE( state_downcast< const State * >() != 0 );
39     BOOST_REQUIRE_NO_THROW( state_downcast< const State & >() );
40     BOOST_REQUIRE( state_cast< const State * >() != 0 );
41     BOOST_REQUIRE_NO_THROW( state_cast< const State & >() );
42   }
43 
44   template< class State >
AssertNotInStateStateCastTest45   void AssertNotInState()
46   {
47     BOOST_REQUIRE( state_downcast< const State * >() == 0 );
48     BOOST_REQUIRE_THROW( state_downcast< const State & >(), std::bad_cast );
49     BOOST_REQUIRE( state_cast< const State * >() == 0 );
50     BOOST_REQUIRE_THROW( state_cast< const State & >(), std::bad_cast );
51   }
52 };
53 
54 template< class State, class FromState >
AssertInState(const FromState & theState)55 void AssertInState( const FromState & theState )
56 {
57   BOOST_REQUIRE( theState.template state_downcast< const State * >() != 0 );
58   BOOST_REQUIRE_NO_THROW( theState.template state_downcast< const State & >() );
59   BOOST_REQUIRE( theState.template state_cast< const State * >() != 0 );
60   BOOST_REQUIRE_NO_THROW( theState.template state_cast< const State & >() );
61 }
62 
63 template< class State, class FromState >
AssertNotInState(const FromState & theState)64 void AssertNotInState( const FromState & theState )
65 {
66   BOOST_REQUIRE( theState.template state_downcast< const State * >() == 0 );
67   BOOST_REQUIRE_THROW( theState.template state_downcast< const State & >(), std::bad_cast );
68   BOOST_REQUIRE( theState.template state_cast< const State * >() == 0 );
69   BOOST_REQUIRE_THROW( theState.template state_cast< const State & >(), std::bad_cast );
70 }
71 
72 struct B;
73 struct C;
74 struct D;
75 struct A : sc::simple_state< A, StateCastTest, mpl::list< C, D > >
76 {
77   typedef sc::transition< EvToB, B > reactions;
78 };
79 
80   struct E;
81   struct C : sc::simple_state< C, A::orthogonal< 0 >, E > {};
82 
83     struct E : sc::state< E, C >
84     {
85       typedef sc::custom_reaction< EvCheck > reactions;
86 
EE87       E( my_context ctx ) : my_base( ctx )
88       {
89         post_event( boost::intrusive_ptr< EvCheck >( new EvCheck() ) );
90       }
91 
92       sc::result react( const EvCheck & );
93     };
94 
95     struct F : sc::state< F, C >
96     {
97       typedef sc::custom_reaction< EvCheck > reactions;
98 
FF99       F( my_context ctx ) : my_base( ctx )
100       {
101         post_event( boost::intrusive_ptr< EvCheck >( new EvCheck() ) );
102       }
103 
104       sc::result react( const EvCheck & );
105     };
106 
107   struct G;
108   struct D : sc::simple_state< D, A::orthogonal< 1 >, G > {};
109 
110     struct G : sc::simple_state< G, D > {};
111     struct H : sc::simple_state< H, D > {};
112 
113 struct B : sc::simple_state< B, StateCastTest >
114 {
115   typedef sc::transition< EvToF, F > reactions;
116 };
117 
react(const EvCheck &)118 sc::result E::react( const EvCheck & )
119 {
120   AssertInState< A >( *this );
121   AssertNotInState< B >( *this );
122   AssertInState< C >( *this );
123   AssertInState< D >( *this );
124   AssertInState< E >( *this );
125   AssertNotInState< F >( *this );
126   AssertInState< G >( *this );
127   AssertNotInState< H >( *this );
128   return discard_event();
129 }
130 
react(const EvCheck &)131 sc::result F::react( const EvCheck & )
132 {
133   AssertInState< A >( *this );
134   AssertNotInState< B >( *this );
135   AssertInState< C >( *this );
136   AssertInState< D >( *this );
137   AssertNotInState< E >( *this );
138   AssertInState< F >( *this );
139   AssertInState< G >( *this );
140   AssertNotInState< H >( *this );
141   return discard_event();
142 }
143 
144 
test_main(int,char * [])145 int test_main( int, char* [] )
146 {
147   StateCastTest machine;
148 
149   machine.AssertNotInState< A >();
150   machine.AssertNotInState< B >();
151   machine.AssertNotInState< C >();
152   machine.AssertNotInState< D >();
153   machine.AssertNotInState< E >();
154   machine.AssertNotInState< F >();
155   machine.AssertNotInState< G >();
156   machine.AssertNotInState< H >();
157 
158   machine.initiate();
159 
160   machine.AssertInState< A >();
161   machine.AssertNotInState< B >();
162   machine.AssertInState< C >();
163   machine.AssertInState< D >();
164   machine.AssertInState< E >();
165   machine.AssertNotInState< F >();
166   machine.AssertInState< G >();
167   machine.AssertNotInState< H >();
168 
169   machine.process_event( EvToB() );
170 
171   machine.AssertNotInState< A >();
172   machine.AssertInState< B >();
173   machine.AssertNotInState< C >();
174   machine.AssertNotInState< D >();
175   machine.AssertNotInState< E >();
176   machine.AssertNotInState< F >();
177   machine.AssertNotInState< G >();
178   machine.AssertNotInState< H >();
179 
180   machine.process_event( EvToF() );
181 
182   machine.AssertInState< A >();
183   machine.AssertNotInState< B >();
184   machine.AssertInState< C >();
185   machine.AssertInState< D >();
186   machine.AssertNotInState< E >();
187   machine.AssertInState< F >();
188   machine.AssertInState< G >();
189   machine.AssertNotInState< H >();
190 
191   machine.terminate();
192 
193   machine.AssertNotInState< A >();
194   machine.AssertNotInState< B >();
195   machine.AssertNotInState< C >();
196   machine.AssertNotInState< D >();
197   machine.AssertNotInState< E >();
198   machine.AssertNotInState< F >();
199   machine.AssertNotInState< G >();
200   machine.AssertNotInState< H >();
201 
202   return 0;
203 }
204