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

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