1// Copyright 2010 Christophe Henry
2// henry UNDERSCORE christophe AT hotmail DOT com
3// This is an extended version of the state machine available in the boost::mpl library
4// Distributed under the same license as the original.
5// Copyright for the original version:
6// Copyright 2005 David Abrahams and Aleksey Gurtovoy. Distributed
7// under the Boost Software License, Version 1.0. (See accompanying
8// file LICENSE_1_0.txt or copy at
9// http://www.boost.org/LICENSE_1_0.txt)
10
11#include <iostream>
12// back-end
13#include <boost/msm/back/state_machine.hpp>
14//front-end
15#include <boost/msm/front/state_machine_def.hpp>
16#include <boost/msm/front/euml/euml.hpp>
17#ifndef BOOST_MSM_NONSTANDALONE_TEST
18#define BOOST_TEST_MODULE MyTest
19#endif
20#include <boost/test/unit_test.hpp>
21
22namespace msm = boost::msm;
23namespace mpl = boost::mpl;
24using namespace boost::msm::front::euml;
25
26namespace
27{
28 // events
29 BOOST_MSM_EUML_EVENT(play)
30 BOOST_MSM_EUML_EVENT(end_pause)
31 BOOST_MSM_EUML_EVENT(stop)
32 BOOST_MSM_EUML_EVENT(pause)
33 BOOST_MSM_EUML_EVENT(open_close)
34 BOOST_MSM_EUML_EVENT(next_song)
35 BOOST_MSM_EUML_EVENT(previous_song)
36 BOOST_MSM_EUML_EVENT(error_found)
37 BOOST_MSM_EUML_EVENT(end_error)
38 BOOST_MSM_EUML_EVENT(do_terminate)
39
40 // Flags. Allow information about a property of the current state
41 BOOST_MSM_EUML_FLAG(PlayingPaused)
42 BOOST_MSM_EUML_FLAG(CDLoaded)
43 BOOST_MSM_EUML_FLAG(FirstSongPlaying)
44
45 // A "complicated" event type that carries some data.
46 BOOST_MSM_EUML_DECLARE_ATTRIBUTE(std::string,cd_name)
47 BOOST_MSM_EUML_ATTRIBUTES((attributes_ << cd_name ), cd_detected_attributes)
48 BOOST_MSM_EUML_EVENT_WITH_ATTRIBUTES(cd_detected,cd_detected_attributes)
49
50 //states
51 BOOST_MSM_EUML_DECLARE_ATTRIBUTE(unsigned int,entry_counter)
52 BOOST_MSM_EUML_DECLARE_ATTRIBUTE(unsigned int,exit_counter)
53
54 BOOST_MSM_EUML_STATE(( ++state_(entry_counter),++state_(exit_counter),
55 attributes_ << entry_counter << exit_counter, configure_ << play),Empty)
56 BOOST_MSM_EUML_STATE(( ++state_(entry_counter),++state_(exit_counter),
57 attributes_ << entry_counter << exit_counter, configure_<< CDLoaded << play),Open)
58 BOOST_MSM_EUML_STATE(( ++state_(entry_counter),++state_(exit_counter),
59 attributes_ << entry_counter << exit_counter, configure_<< CDLoaded),Stopped)
60 BOOST_MSM_EUML_STATE(( ++state_(entry_counter),++state_(exit_counter),
61 attributes_ << entry_counter << exit_counter, configure_<< CDLoaded << PlayingPaused),Paused)
62
63 BOOST_MSM_EUML_STATE(( ++state_(entry_counter),++state_(exit_counter),attributes_ << entry_counter << exit_counter),AllOk)
64 BOOST_MSM_EUML_TERMINATE_STATE(( ++state_(entry_counter),++state_(exit_counter),attributes_ << entry_counter << exit_counter),
65 ErrorTerminate)
66 BOOST_MSM_EUML_INTERRUPT_STATE(( end_error,++state_(entry_counter),++state_(exit_counter),attributes_ << entry_counter << exit_counter),
67 ErrorMode)
68
69 // Playing is now a state machine itself.
70 BOOST_MSM_EUML_DECLARE_ATTRIBUTE(unsigned int,start_next_song_counter)
71 BOOST_MSM_EUML_DECLARE_ATTRIBUTE(unsigned int,start_prev_song_guard_counter)
72
73 BOOST_MSM_EUML_STATE(( ++state_(entry_counter),++state_(exit_counter),
74 attributes_ << entry_counter << exit_counter, configure_<< FirstSongPlaying ),Song1)
75 BOOST_MSM_EUML_STATE(( ++state_(entry_counter),++state_(exit_counter),attributes_ << entry_counter << exit_counter),Song2)
76 BOOST_MSM_EUML_STATE(( ++state_(entry_counter),++state_(exit_counter),attributes_ << entry_counter << exit_counter),Song3)
77
78 // Playing has a transition table
79 BOOST_MSM_EUML_TRANSITION_TABLE((
80 // +------------------------------------------------------------------------------+
81 Song2 == Song1 + next_song ,
82 Song1 == Song2 + previous_song [True_()] / ++fsm_(start_prev_song_guard_counter) ,
83 Song3 == Song2 + next_song / ++fsm_(start_next_song_counter) ,
84 Song2 == Song3 + previous_song [True_()] / ++fsm_(start_prev_song_guard_counter)
85 // +------------------------------------------------------------------------------+
86 ),playing_transition_table )
87
88 BOOST_MSM_EUML_DECLARE_STATE_MACHINE( (playing_transition_table, //STT
89 init_ << Song1, // Init State
90 ++state_(entry_counter), // Entry
91 ++state_(exit_counter), // Exit
92 attributes_ << entry_counter << exit_counter
93 << start_next_song_counter
94 << start_prev_song_guard_counter, // Attributes
95 configure_<< PlayingPaused << CDLoaded //flags
96 ),Playing_)
97
98 // back-end
99 typedef msm::back::state_machine<Playing_> Playing_type;
100 Playing_type const Playing;
101
102 //fsm
103 BOOST_MSM_EUML_DECLARE_ATTRIBUTE(unsigned int,start_playback_counter)
104 BOOST_MSM_EUML_DECLARE_ATTRIBUTE(unsigned int,can_close_drawer_counter)
105 BOOST_MSM_EUML_DECLARE_ATTRIBUTE(unsigned int,report_error_counter)
106 BOOST_MSM_EUML_DECLARE_ATTRIBUTE(unsigned int,report_end_error_counter)
107 BOOST_MSM_EUML_ACTION(No_Transition)
108 {
109 template <class FSM,class Event>
110 void operator()(Event const&,FSM&,int)
111 {
112 BOOST_FAIL("no_transition called!");
113 }
114 };
115
116 BOOST_MSM_EUML_TRANSITION_TABLE((
117 Playing == Stopped + play / ++fsm_(start_playback_counter),
118 Playing == Paused + end_pause ,
119 // +------------------------------------------------------------------------------+
120 Empty == Open + open_close / ++fsm_(can_close_drawer_counter),
121 // +------------------------------------------------------------------------------+
122 Open == Empty + open_close ,
123 Open == Paused + open_close ,
124 Open == Stopped + open_close ,
125 Open == Playing + open_close ,
126 // +------------------------------------------------------------------------------+
127 Paused == Playing + pause ,
128 // +------------------------------------------------------------------------------+
129 Stopped == Playing + stop ,
130 Stopped == Paused + stop ,
131 Stopped == Empty + cd_detected ,
132 Stopped == Stopped + stop ,
133 ErrorMode == AllOk + error_found / ++fsm_(report_error_counter),
134 AllOk == ErrorMode+ end_error / ++fsm_(report_end_error_counter),
135 ErrorTerminate== AllOk +do_terminate
136 // +------------------------------------------------------------------------------+
137 ),transition_table)
138
139 BOOST_MSM_EUML_DECLARE_STATE_MACHINE(( transition_table, //STT
140 init_ << Empty << AllOk, // Init State
141 no_action, // Entry
142 no_action, // Exit
143 attributes_ << start_playback_counter << can_close_drawer_counter
144 << report_error_counter << report_end_error_counter, // Attributes
145 configure_ << no_configure_, // configuration
146 No_Transition // no_transition handler
147 ),
148 player_) //fsm name
149
150 // Pick a back-end
151 typedef msm::back::state_machine<player_> player;
152
153 //static char const* const state_names[] = { "Stopped", "Paused","Open", "Empty", "Playing" ,"AllOk","ErrorMode","ErrorTerminate" };
154
155 BOOST_AUTO_TEST_CASE( my_test )
156 {
157 player p;
158 // needed to start the highest-level SM. This will call on_entry and mark the start of the SM
159 p.start();
160 // test deferred event
161 // deferred in Empty and Open, will be handled only after event cd_detected
162 p.process_event(evt: play);
163 BOOST_CHECK_MESSAGE(p.current_state()[0] == 3,"Empty should be active"); //Empty
164 BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(Open)&>().get_attribute(exit_counter) == 0,
165 "Open exit not called correctly");
166 BOOST_CHECK_MESSAGE(p.get_state<Playing_type&>().get_attribute(entry_counter) == 0,"Playing entry not called correctly");
167 BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(Empty)&>().get_attribute(entry_counter) == 1,
168 "Empty entry not called correctly");
169 //flags
170 BOOST_CHECK_MESSAGE(p.is_flag_active<BOOST_MSM_EUML_FLAG_NAME(CDLoaded)>() == false,"CDLoaded should not be active");
171
172 p.process_event(evt: open_close);
173 BOOST_CHECK_MESSAGE(p.current_state()[0] == 2,"Open should be active"); //Open
174 BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(Empty)&>().get_attribute(exit_counter) == 1,
175 "Empty exit not called correctly");
176 BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(Open)&>().get_attribute(entry_counter) == 1,
177 "Open entry not called correctly");
178
179 p.process_event(evt: open_close);
180 BOOST_CHECK_MESSAGE(p.current_state()[0] == 3,"Empty should be active"); //Empty
181 BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(Open)&>().get_attribute(exit_counter) == 1,
182 "Open exit not called correctly");
183 BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(Empty)&>().get_attribute(entry_counter) == 2,
184 "Empty entry not called correctly");
185 BOOST_CHECK_MESSAGE(p.get_attribute(can_close_drawer_counter) == 1,"guard not called correctly");
186
187 //deferred event should have been processed
188 p.process_event(evt: cd_detected("louie, louie"));
189 BOOST_CHECK_MESSAGE(p.current_state()[0] == 4,"Playing should be active"); //Playing
190 BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(Empty)&>().get_attribute(exit_counter) == 2,
191 "Empty exit not called correctly");
192 BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(Stopped)&>().get_attribute(entry_counter) == 1,
193 "Stopped entry not called correctly");
194 BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(Stopped)&>().get_attribute(exit_counter) == 1,
195 "Stopped exit not called correctly");
196 BOOST_CHECK_MESSAGE(p.get_state<Playing_type&>().get_attribute(entry_counter) == 1,"Playing entry not called correctly");
197 BOOST_CHECK_MESSAGE(p.get_attribute(start_playback_counter) == 1,"action not called correctly");
198 BOOST_CHECK_MESSAGE(p.get_state<Playing_type&>().current_state()[0] == 0,"Song1 should be active");
199 BOOST_CHECK_MESSAGE(
200 p.get_state<Playing_type&>().get_state<BOOST_MSM_EUML_STATE_NAME(Song1)&>().get_attribute(entry_counter) == 1,
201 "Song1 entry not called correctly");
202
203 //flags
204 BOOST_CHECK_MESSAGE(p.is_flag_active<BOOST_MSM_EUML_FLAG_NAME(PlayingPaused)>() == true,"PlayingPaused should be active");
205 BOOST_CHECK_MESSAGE(p.is_flag_active<BOOST_MSM_EUML_FLAG_NAME(FirstSongPlaying)>() == true,"FirstSongPlaying should be active");
206
207
208 p.process_event(evt: next_song);
209 BOOST_CHECK_MESSAGE(p.current_state()[0] == 4,"Playing should be active"); //Playing
210 BOOST_CHECK_MESSAGE(p.get_state<Playing_type&>().current_state()[0] == 1,"Song2 should be active");
211 BOOST_CHECK_MESSAGE(
212 p.get_state<Playing_type&>().get_state<BOOST_MSM_EUML_STATE_NAME(Song2)&>().get_attribute(entry_counter) == 1,
213 "Song2 entry not called correctly");
214 BOOST_CHECK_MESSAGE(
215 p.get_state<Playing_type&>().get_state<BOOST_MSM_EUML_STATE_NAME(Song1)&>().get_attribute(exit_counter) == 1,
216 "Song1 exit not called correctly");
217 BOOST_CHECK_MESSAGE(
218 p.get_state<Playing_type&>().get_attribute(start_next_song_counter) == 0,
219 "submachine action not called correctly");
220
221 p.process_event(evt: next_song);
222 BOOST_CHECK_MESSAGE(p.current_state()[0] == 4,"Playing should be active"); //Playing
223 BOOST_CHECK_MESSAGE(p.get_state<Playing_type&>().current_state()[0] == 2,"Song3 should be active");
224 BOOST_CHECK_MESSAGE(
225 p.get_state<Playing_type&>().get_state<BOOST_MSM_EUML_STATE_NAME(Song3)&>().get_attribute(entry_counter) == 1,
226 "Song3 entry not called correctly");
227 BOOST_CHECK_MESSAGE(
228 p.get_state<Playing_type&>().get_state<BOOST_MSM_EUML_STATE_NAME(Song2)&>().get_attribute(exit_counter) == 1,
229 "Song2 exit not called correctly");
230 BOOST_CHECK_MESSAGE(
231 p.get_state<Playing_type&>().get_attribute(start_next_song_counter) == 1,
232 "submachine action not called correctly");
233
234 p.process_event(evt: previous_song);
235 BOOST_CHECK_MESSAGE(p.current_state()[0] == 4,"Playing should be active"); //Playing
236 BOOST_CHECK_MESSAGE(p.get_state<Playing_type&>().current_state()[0] == 1,"Song2 should be active");
237 BOOST_CHECK_MESSAGE(
238 p.get_state<Playing_type&>().get_state<BOOST_MSM_EUML_STATE_NAME(Song2)&>().get_attribute(entry_counter) == 2,
239 "Song2 entry not called correctly");
240 BOOST_CHECK_MESSAGE(
241 p.get_state<Playing_type&>().get_state<BOOST_MSM_EUML_STATE_NAME(Song3)&>().get_attribute(exit_counter) == 1,
242 "Song3 exit not called correctly");
243 BOOST_CHECK_MESSAGE(
244 p.get_state<Playing_type&>().get_attribute(start_prev_song_guard_counter) == 1,
245 "submachine guard not called correctly");
246 //flags
247 BOOST_CHECK_MESSAGE(p.is_flag_active<BOOST_MSM_EUML_FLAG_NAME(PlayingPaused)>() == true,"PlayingPaused should be active");
248 BOOST_CHECK_MESSAGE(p.is_flag_active<BOOST_MSM_EUML_FLAG_NAME(FirstSongPlaying)>() == false,"FirstSongPlaying should not be active");
249
250 p.process_event(evt: pause());
251 BOOST_CHECK_MESSAGE(p.current_state()[0] == 1,"Paused should be active"); //Paused
252 BOOST_CHECK_MESSAGE(p.get_state<Playing_type&>().get_attribute(exit_counter) == 1,"Playing exit not called correctly");
253 BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(Paused)&>().get_attribute(entry_counter) == 1,
254 "Paused entry not called correctly");
255 //flags
256 BOOST_CHECK_MESSAGE(p.is_flag_active<BOOST_MSM_EUML_FLAG_NAME(PlayingPaused)>() == true,"PlayingPaused should be active");
257
258 // go back to Playing
259 p.process_event(evt: end_pause);
260 BOOST_CHECK_MESSAGE(p.current_state()[0] == 4,"Playing should be active"); //Playing
261 BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(Paused)&>().get_attribute(exit_counter) == 1,
262 "Paused exit not called correctly");
263 BOOST_CHECK_MESSAGE(p.get_state<Playing_type&>().get_attribute(entry_counter) == 2,"Playing entry not called correctly");
264
265 p.process_event(evt: pause);
266 BOOST_CHECK_MESSAGE(p.current_state()[0] == 1,"Paused should be active"); //Paused
267 BOOST_CHECK_MESSAGE(p.get_state<Playing_type&>().get_attribute(exit_counter) == 2,"Playing exit not called correctly");
268 BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(Paused)&>().get_attribute(entry_counter) == 2,
269 "Paused entry not called correctly");
270
271 p.process_event(evt: stop);
272 BOOST_CHECK_MESSAGE(p.current_state()[0] == 0,"Stopped should be active"); //Stopped
273 BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(Paused)&>().get_attribute(exit_counter) == 2,
274 "Paused exit not called correctly");
275 BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(Stopped)&>().get_attribute(entry_counter) == 2,
276 "Stopped entry not called correctly");
277 //flags
278 BOOST_CHECK_MESSAGE(p.is_flag_active<BOOST_MSM_EUML_FLAG_NAME(PlayingPaused)>() == false,"PlayingPaused should not be active");
279 BOOST_CHECK_MESSAGE(p.is_flag_active<BOOST_MSM_EUML_FLAG_NAME(CDLoaded)>() == true,"CDLoaded should be active");
280 //BOOST_CHECK_MESSAGE(p.is_flag_active<BOOST_MSM_EUML_FLAG_NAME(CDLoaded),player::Flag_AND>() == false,"CDLoaded with AND should not be active");
281
282 p.process_event(evt: stop);
283 BOOST_CHECK_MESSAGE(p.current_state()[0] == 0,"Stopped should be active"); //Stopped
284 BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(Stopped)&>().get_attribute(exit_counter) == 2,
285 "Stopped exit not called correctly");
286 BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(Stopped)&>().get_attribute(entry_counter) == 3,
287 "Stopped entry not called correctly");
288
289 //test interrupt
290 BOOST_CHECK_MESSAGE(p.current_state()[1] == 5,"AllOk should be active"); //AllOk
291 p.process_event(evt: error_found);
292 BOOST_CHECK_MESSAGE(p.current_state()[1] == 6,"ErrorMode should be active"); //ErrorMode
293 BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(AllOk)&>().get_attribute(exit_counter) == 1,
294 "AllOk exit not called correctly");
295 BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(ErrorMode)&>().get_attribute(entry_counter) == 1,
296 "ErrorMode entry not called correctly");
297
298 // try generating more events
299 p.process_event(evt: play);
300 BOOST_CHECK_MESSAGE(p.current_state()[1] == 6,"ErrorMode should be active"); //ErrorMode
301 BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(AllOk)&>().get_attribute(exit_counter) == 1,
302 "AllOk exit not called correctly");
303 BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(ErrorMode)&>().get_attribute(entry_counter) == 1,
304 "ErrorMode entry not called correctly");
305 BOOST_CHECK_MESSAGE(p.current_state()[0] == 0,"Stopped should be active"); //Stopped
306 BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(Stopped)&>().get_attribute(exit_counter) == 2,
307 "Stopped exit not called correctly");
308 BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(Stopped)&>().get_attribute(entry_counter) == 3,
309 "Stopped entry not called correctly");
310
311 p.process_event(evt: end_error);
312 BOOST_CHECK_MESSAGE(p.current_state()[1] == 5,"AllOk should be active"); //AllOk
313 BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(ErrorMode)&>().get_attribute(exit_counter) == 1,
314 "ErrorMode exit not called correctly");
315 BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(AllOk)&>().get_attribute(entry_counter) == 2,
316 "AllOk entry not called correctly");
317
318 p.process_event(evt: play);
319 BOOST_CHECK_MESSAGE(p.current_state()[0] == 4,"Playing should be active"); //Playing
320 BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(Stopped)&>().get_attribute(exit_counter) == 3,
321 "Stopped exit not called correctly");
322 BOOST_CHECK_MESSAGE(p.get_state<Playing_type&>().get_attribute(entry_counter) == 3,"Playing entry not called correctly");
323
324 //test terminate
325 BOOST_CHECK_MESSAGE(p.current_state()[1] == 5,"AllOk should be active"); //AllOk
326 p.process_event(evt: do_terminate);
327 BOOST_CHECK_MESSAGE(p.current_state()[1] == 7,"ErrorTerminate should be active"); //ErrorTerminate
328 BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(AllOk)&>().get_attribute(exit_counter) == 2,
329 "AllOk exit not called correctly");
330 BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(ErrorTerminate)&>().get_attribute(entry_counter) == 1,
331 "ErrorTerminate entry not called correctly");
332
333 // try generating more events
334 p.process_event(evt: stop);
335 BOOST_CHECK_MESSAGE(p.current_state()[1] == 7,"ErrorTerminate should be active"); //ErrorTerminate
336 BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(ErrorTerminate)&>().get_attribute(exit_counter) == 0,
337 "ErrorTerminate exit not called correctly");
338 BOOST_CHECK_MESSAGE(p.current_state()[0] == 4,"Playing should be active"); //Playing
339 BOOST_CHECK_MESSAGE(p.get_state<Playing_type&>().get_attribute(exit_counter) == 2,"Playing exit not called correctly");
340 BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(Stopped)&>().get_attribute(entry_counter) == 3,
341 "Stopped entry not called correctly");
342
343 p.process_event(evt: end_error());
344 BOOST_CHECK_MESSAGE(p.current_state()[1] == 7,"ErrorTerminate should be active"); //ErrorTerminate
345 BOOST_CHECK_MESSAGE(p.current_state()[0] == 4,"Playing should be active"); //Playing
346 BOOST_CHECK_MESSAGE(p.get_state<Playing_type&>().get_attribute(exit_counter) == 2,"Playing exit not called correctly");
347 BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(Stopped)&>().get_attribute(entry_counter) == 3,
348 "Stopped entry not called correctly");
349
350 p.process_event(evt: stop());
351 BOOST_CHECK_MESSAGE(p.current_state()[1] == 7,"ErrorTerminate should be active"); //ErrorTerminate
352 BOOST_CHECK_MESSAGE(p.current_state()[0] == 4,"Playing should be active"); //Playing
353 BOOST_CHECK_MESSAGE(p.get_state<Playing_type&>().get_attribute(exit_counter) == 2,"Playing exit not called correctly");
354 BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(Stopped)&>().get_attribute(entry_counter) == 3,
355 "Stopped entry not called correctly");
356
357 }
358}
359
360

source code of boost/libs/msm/test/OrthogonalDeferredEuml.cpp