Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: downloads/boost_1_34_1/libs/statechart/test/CustomReactionTest.cpp @ 45

Last change on this file since 45 was 29, checked in by landauf, 17 years ago

updated boost from 1_33_1 to 1_34_1

File size: 9.9 KB
Line 
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/transition.hpp>
13#include <boost/statechart/custom_reaction.hpp>
14
15#include <boost/mpl/list.hpp>
16
17#include <boost/test/test_tools.hpp>
18
19#include <set>
20#include <map>
21#include <string>
22
23#include <cstddef> // size_t
24
25
26
27namespace sc = boost::statechart;
28namespace mpl = boost::mpl;
29
30
31
32struct EvToC : sc::event< EvToC > {};
33struct EvToD : sc::event< EvToD > {};
34
35struct EvDiscardNever : sc::event< EvDiscardNever > {};
36struct EvDiscardInB : sc::event< EvDiscardInB > {};
37struct EvDiscardInD : sc::event< EvDiscardInD > {};
38
39struct EvTransit : sc::event< EvTransit > {};
40struct EvTransitWithAction : sc::event< EvTransitWithAction > {};
41struct EvDefer : sc::event< EvDefer > {};
42struct EvTerminate : sc::event< EvTerminate > {};
43
44
45struct A;
46struct CustomReactionTest : sc::state_machine< CustomReactionTest, A >
47{
48  public:
49    //////////////////////////////////////////////////////////////////////////
50    CustomReactionTest();
51
52    void Visited( const state_base_type & stt )
53    {
54      const StateNamesMap::const_iterator found =
55        stateNamesMap_.find( stt.dynamic_type() );
56      BOOST_REQUIRE( found != stateNamesMap_.end() );
57      visitedStates_.insert( found->second );
58    }
59
60    void ClearVisited()
61    {
62      visitedStates_.clear();
63    }
64
65    void AssertVisitedAll( const std::string & stateNames ) const
66    {
67      for ( std::string::const_iterator expectedName = stateNames.begin();
68        expectedName != stateNames.end(); ++expectedName )
69      {
70        BOOST_REQUIRE( visitedStates_.find(
71          std::string( 1, *expectedName ) ) != visitedStates_.end() );
72      }
73    }
74
75    void AssertVisitedOne( const std::string & stateNames ) const
76    {
77      std::size_t found = 0;
78
79      for ( std::string::const_iterator actualName = stateNames.begin();
80        actualName != stateNames.end(); ++actualName )
81      {
82        found = found + ( visitedStates_.find(
83          std::string( 1, *actualName ) ) != visitedStates_.end() ) ? 1 : 0;
84      }
85
86      BOOST_REQUIRE( found == 1 );
87    }
88
89    void TransitionAction( const EvTransitWithAction & ) {}
90
91  private:
92    //////////////////////////////////////////////////////////////////////////
93    typedef std::map< state_base_type::id_type, std::string > StateNamesMap;
94    typedef std::set< std::string > VisitedStates;
95
96    StateNamesMap stateNamesMap_;
97    VisitedStates visitedStates_;
98};
99
100struct B;
101struct A : sc::simple_state< A, CustomReactionTest, B >
102{
103  typedef mpl::list<
104    sc::custom_reaction< EvDiscardNever >,
105    sc::custom_reaction< EvDiscardInB >,
106    sc::custom_reaction< EvDiscardInD >,
107    sc::custom_reaction< EvDefer >,
108    sc::custom_reaction< EvTerminate >,
109    sc::custom_reaction< EvTransitWithAction >,
110    sc::custom_reaction< EvTransit >
111  > reactions;
112
113  sc::result react( const EvDiscardNever & )
114  {
115    outermost_context().Visited( *this );
116    return forward_event();
117  }
118
119  sc::result react( const EvDiscardInB & )
120  {
121    BOOST_FAIL( "An event discarded in B must never reach A" );
122    return discard_event();
123  }
124
125  sc::result react( const EvDiscardInD & )
126  {
127    BOOST_FAIL( "An event discarded in D must never reach B" );
128    return discard_event();
129  }
130
131  // The following code is here just to make sure that calls to the transit<>,
132  // defer_event and terminate functions actually compile.
133  // Their functionality is tested extensively in TransitionTest,
134  // DeferralTest and TerminationTest with appropriate reactions. Internally,
135  // these reactions call exactly the same functions as the following custom
136  // reactions call.
137  sc::result react( const EvDefer & )
138  {
139    return defer_event();
140  }
141
142  sc::result react( const EvTerminate & )
143  {
144    return terminate();
145  }
146
147  sc::result react( const EvTransit & )
148  {
149    return transit< A >();
150  }
151
152  sc::result react( const EvTransitWithAction & evt )
153  {
154    return transit< A >( &CustomReactionTest::TransitionAction, evt );
155  }
156};
157
158  struct C;
159  struct B : sc::simple_state< B, A, C >
160  {
161    typedef mpl::list<
162      sc::custom_reaction< EvDiscardNever >,
163      sc::custom_reaction< EvDiscardInB >,
164      sc::custom_reaction< EvDiscardInD >
165    > reactions;
166
167    sc::result react( const EvDiscardNever & )
168    {
169      outermost_context().Visited( *this );
170      return forward_event();
171    }
172
173    sc::result react( const EvDiscardInB & )
174    {
175      outermost_context().Visited( *this );
176      return discard_event();
177    }
178
179    sc::result react( const EvDiscardInD & )
180    {
181      BOOST_FAIL( "An event discarded in D must never reach B" );
182      return discard_event();
183    }
184  };
185
186    struct E;
187    struct F;
188    struct D : sc::simple_state< D, B, mpl::list< E, F > >
189    {
190      typedef mpl::list<
191        sc::transition< EvToC, C >,
192        sc::custom_reaction< EvDiscardNever >,
193        sc::custom_reaction< EvDiscardInB >,
194        sc::custom_reaction< EvDiscardInD >
195      > reactions;
196
197      sc::result react( const EvDiscardNever & )
198      {
199        outermost_context().Visited( *this );
200        return forward_event();
201      }
202
203      sc::result react( const EvDiscardInB & )
204      {
205        outermost_context().Visited( *this );
206        return forward_event();
207      }
208
209      sc::result react( const EvDiscardInD & )
210      {
211        outermost_context().Visited( *this );
212        return discard_event();
213      }
214    };
215
216      struct E : sc::simple_state< E, D::orthogonal< 0 >  >
217      {
218        typedef mpl::list<
219          sc::custom_reaction< EvDiscardNever >,
220          sc::custom_reaction< EvDiscardInB >,
221          sc::custom_reaction< EvDiscardInD >
222        > reactions;
223
224        sc::result react( const EvDiscardNever & )
225        {
226          outermost_context().Visited( *this );
227          return forward_event();
228        }
229
230        sc::result react( const EvDiscardInB & )
231        {
232          outermost_context().Visited( *this );
233          return forward_event();
234        }
235
236        sc::result react( const EvDiscardInD & )
237        {
238          outermost_context().Visited( *this );
239          return forward_event();
240        }
241      };
242
243      struct F : sc::simple_state< F, D::orthogonal< 1 > >
244      {
245        typedef mpl::list<
246          sc::custom_reaction< EvDiscardNever >,
247          sc::custom_reaction< EvDiscardInB >,
248          sc::custom_reaction< EvDiscardInD >
249        > reactions;
250
251        sc::result react( const EvDiscardNever & )
252        {
253          outermost_context().Visited( *this );
254          return forward_event();
255        }
256
257        sc::result react( const EvDiscardInB & )
258        {
259          outermost_context().Visited( *this );
260          return forward_event();
261        }
262
263        sc::result react( const EvDiscardInD & )
264        {
265          outermost_context().Visited( *this );
266          return forward_event();
267        }
268      };
269
270    struct C : sc::simple_state< C, B >
271    {
272      typedef mpl::list<
273        sc::transition< EvToD, D >,
274        sc::custom_reaction< EvDiscardNever >,
275        sc::custom_reaction< EvDiscardInB >,
276        sc::custom_reaction< EvDiscardInD >
277      > reactions;
278
279      sc::result react( const EvDiscardNever & )
280      {
281        outermost_context().Visited( *this );
282        return forward_event();
283      }
284
285      sc::result react( const EvDiscardInB & )
286      {
287        outermost_context().Visited( *this );
288        return forward_event();
289      }
290
291      sc::result react( const EvDiscardInD & )
292      {
293        outermost_context().Visited( *this );
294        return forward_event();
295      }
296    };
297
298CustomReactionTest::CustomReactionTest()
299{
300  // We're not using custom type information to make this test work even when
301  // BOOST_STATECHART_USE_NATIVE_RTTI is defined
302  stateNamesMap_[ A::static_type() ] = "A";
303  stateNamesMap_[ B::static_type() ] = "B";
304  stateNamesMap_[ C::static_type() ] = "C";
305  stateNamesMap_[ D::static_type() ] = "D";
306  stateNamesMap_[ E::static_type() ] = "E";
307  stateNamesMap_[ F::static_type() ] = "F";
308}
309
310
311struct X1;
312struct CustomReactionEventBaseTest : sc::state_machine< CustomReactionEventBaseTest, X1 >
313{
314  public:
315    CustomReactionEventBaseTest() : reactionCount_( 0 ) {}
316
317    void IncrementReactionCount()
318    {
319      ++reactionCount_;
320    }
321
322    unsigned int GetReactionCount() const
323    {
324      return reactionCount_;
325    }
326
327  private:
328    unsigned int reactionCount_;
329};
330
331struct X1 : sc::simple_state< X1, CustomReactionEventBaseTest >
332{
333  typedef sc::custom_reaction< sc::event_base > reactions;
334
335  sc::result react( const sc::event_base & )
336  {
337    outermost_context().IncrementReactionCount();
338    return discard_event();
339  }
340};
341
342
343int test_main( int, char* [] )
344{
345  CustomReactionTest machine;
346  machine.initiate();
347
348  machine.process_event( EvDiscardNever() );
349  machine.AssertVisitedAll( "ABC" );
350  machine.ClearVisited();
351
352  machine.process_event( EvDiscardInB() );
353  machine.AssertVisitedAll( "BC" );
354  machine.process_event( EvToD() );
355  machine.ClearVisited();
356
357  machine.process_event( EvDiscardNever() );
358  machine.AssertVisitedAll( "ABDEF" );
359  machine.ClearVisited();
360
361  machine.process_event( EvDiscardInD() );
362  machine.AssertVisitedAll( "D" );
363  machine.AssertVisitedOne( "EF" );
364  machine.ClearVisited();
365
366  machine.process_event( EvDiscardInB() );
367  machine.AssertVisitedAll( "BD" );
368  machine.AssertVisitedOne( "EF" );
369  machine.ClearVisited();
370
371
372  CustomReactionEventBaseTest eventBaseMachine;
373  eventBaseMachine.initiate();
374  BOOST_REQUIRE( eventBaseMachine.GetReactionCount() == 0 );
375  eventBaseMachine.process_event( EvToC() );
376  BOOST_REQUIRE( eventBaseMachine.GetReactionCount() == 1 );
377  eventBaseMachine.process_event( EvToD() );
378  BOOST_REQUIRE( eventBaseMachine.GetReactionCount() == 2 );
379
380  return 0;
381}
Note: See TracBrowser for help on using the repository browser.