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 | |
22 | namespace msm = boost::msm; |
23 | namespace mpl = boost::mpl; |
24 | using namespace boost::msm::front::euml; |
25 | |
26 | namespace |
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 | |