]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/msm/test/CompositeEuml.cpp
add subtree-ish sources for 12.0.3
[ceph.git] / ceph / src / boost / libs / msm / test / CompositeEuml.cpp
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 #include <boost/msm/back/state_machine.hpp>
13 #include <boost/msm/front/euml/euml.hpp>
14
15 #ifndef BOOST_MSM_NONSTANDALONE_TEST
16 #define BOOST_TEST_MODULE MyTest
17 #endif
18 #include <boost/test/unit_test.hpp>
19
20 using namespace std;
21 using namespace boost::msm::front::euml;
22 namespace msm = boost::msm;
23
24 namespace
25 {
26 // A "complicated" event type that carries some data.
27 enum DiskTypeEnum
28 {
29 DISK_CD=0,
30 DISK_DVD=1
31 };
32 // events
33 BOOST_MSM_EUML_EVENT(play)
34 BOOST_MSM_EUML_EVENT(end_pause)
35 BOOST_MSM_EUML_EVENT(stop)
36 BOOST_MSM_EUML_EVENT(pause)
37 BOOST_MSM_EUML_EVENT(open_close)
38 BOOST_MSM_EUML_EVENT(next_song)
39 BOOST_MSM_EUML_EVENT(previous_song)
40 BOOST_MSM_EUML_EVENT(region2_evt)
41 // A "complicated" event type that carries some data.
42 BOOST_MSM_EUML_DECLARE_ATTRIBUTE(std::string,cd_name)
43 BOOST_MSM_EUML_DECLARE_ATTRIBUTE(DiskTypeEnum,cd_type)
44 BOOST_MSM_EUML_ATTRIBUTES((attributes_ << cd_name << cd_type ), cd_detected_attributes)
45 BOOST_MSM_EUML_EVENT_WITH_ATTRIBUTES(cd_detected,cd_detected_attributes)
46
47 //states
48 BOOST_MSM_EUML_DECLARE_ATTRIBUTE(unsigned int,entry_counter)
49 BOOST_MSM_EUML_DECLARE_ATTRIBUTE(unsigned int,exit_counter)
50
51 BOOST_MSM_EUML_STATE(( ++state_(entry_counter),++state_(exit_counter),attributes_ << entry_counter << exit_counter),Empty)
52 BOOST_MSM_EUML_STATE(( ++state_(entry_counter),++state_(exit_counter),attributes_ << entry_counter << exit_counter),Open)
53 BOOST_MSM_EUML_STATE(( ++state_(entry_counter),++state_(exit_counter),attributes_ << entry_counter << exit_counter),Stopped)
54 BOOST_MSM_EUML_STATE(( ++state_(entry_counter),++state_(exit_counter),attributes_ << entry_counter << exit_counter),Paused)
55
56 // Playing is now a state machine itself.
57 BOOST_MSM_EUML_DECLARE_ATTRIBUTE(unsigned int,start_next_song_counter)
58 BOOST_MSM_EUML_DECLARE_ATTRIBUTE(unsigned int,start_prev_song_guard_counter)
59 // It has 5 substates
60 BOOST_MSM_EUML_STATE(( ++state_(entry_counter),++state_(exit_counter),attributes_ << entry_counter << exit_counter),Song1)
61 BOOST_MSM_EUML_STATE(( ++state_(entry_counter),++state_(exit_counter),attributes_ << entry_counter << exit_counter),Song2)
62 BOOST_MSM_EUML_STATE(( ++state_(entry_counter),++state_(exit_counter),attributes_ << entry_counter << exit_counter),Song3)
63 BOOST_MSM_EUML_STATE(( ++state_(entry_counter),++state_(exit_counter),attributes_ << entry_counter << exit_counter),Region2State1)
64 BOOST_MSM_EUML_STATE(( ++state_(entry_counter),++state_(exit_counter),attributes_ << entry_counter << exit_counter),Region2State2)
65
66 // Playing has a transition table
67 BOOST_MSM_EUML_TRANSITION_TABLE((
68 // +------------------------------------------------------------------------------+
69 Song2 == Song1 + next_song ,
70 Song1 == Song2 + previous_song [True_()] / ++fsm_(start_prev_song_guard_counter) ,
71 Song3 == Song2 + next_song / ++fsm_(start_next_song_counter) ,
72 Song2 == Song3 + previous_song [True_()] / ++fsm_(start_prev_song_guard_counter) ,
73 Region2State2 == Region2State1 + region2_evt
74 // +------------------------------------------------------------------------------+
75 ),playing_transition_table )
76
77 BOOST_MSM_EUML_DECLARE_STATE_MACHINE( (playing_transition_table, //STT
78 init_ << Song1 << Region2State1, // Init State
79 ++state_(entry_counter), // Entry
80 ++state_(exit_counter), // Exit
81 attributes_ << entry_counter << exit_counter
82 << start_next_song_counter
83 << start_prev_song_guard_counter // Attributes
84 ),Playing_)
85 // choice of back-end
86 typedef msm::back::state_machine<Playing_> Playing_type;
87 Playing_type const Playing;
88
89
90 //fsm
91 BOOST_MSM_EUML_DECLARE_ATTRIBUTE(unsigned int,start_playback_counter)
92 BOOST_MSM_EUML_DECLARE_ATTRIBUTE(unsigned int,can_close_drawer_counter)
93 BOOST_MSM_EUML_DECLARE_ATTRIBUTE(unsigned int,test_fct_counter)
94 BOOST_MSM_EUML_ACTION(No_Transition)
95 {
96 template <class FSM,class Event>
97 void operator()(Event const&,FSM&,int)
98 {
99 BOOST_FAIL("no_transition called!");
100 }
101 };
102 BOOST_MSM_EUML_ACTION(good_disk_format)
103 {
104 template <class FSM,class EVT,class SourceState,class TargetState>
105 bool operator()(EVT const& evt,FSM&,SourceState& ,TargetState& )
106 {
107 if (evt.get_attribute(cd_type)!=DISK_CD)
108 {
109 return false;
110 }
111 return true;
112 }
113 };
114 BOOST_MSM_EUML_TRANSITION_TABLE((
115 Playing == Stopped + play / (++fsm_(start_playback_counter),++fsm_(test_fct_counter) ),
116 Playing == Paused + end_pause ,
117 // +------------------------------------------------------------------------------+
118 Empty == Open + open_close / ++fsm_(can_close_drawer_counter),
119 // +------------------------------------------------------------------------------+
120 Open == Empty + open_close ,
121 Open == Paused + open_close ,
122 Open == Stopped + open_close ,
123 Open == Playing + open_close ,
124 // +------------------------------------------------------------------------------+
125 Paused == Playing + pause ,
126 // +------------------------------------------------------------------------------+
127 Stopped == Playing + stop ,
128 Stopped == Paused + stop ,
129 Stopped == Empty + cd_detected [good_disk_format ||
130 (event_(cd_type)==Int_<DISK_CD>())] / process_(play) ,
131 Stopped == Stopped + stop
132 // +------------------------------------------------------------------------------+
133 ),transition_table)
134
135 BOOST_MSM_EUML_DECLARE_STATE_MACHINE(( transition_table, //STT
136 init_ << Empty, // Init State
137 no_action, // Entry
138 no_action, // Exit
139 attributes_ << start_playback_counter
140 << can_close_drawer_counter << test_fct_counter, // Attributes
141 configure_ << no_configure_, // configuration
142 No_Transition // no_transition handler
143 ),
144 player_) //fsm name
145
146 typedef msm::back::state_machine<player_> player;
147
148 // static char const* const state_names[] = { "Stopped", "Paused", "Open", "Empty", "Playing" };
149
150
151 BOOST_AUTO_TEST_CASE( my_test )
152 {
153 player p;
154
155 p.start();
156 BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(Empty)&>().get_attribute(entry_counter) == 1,
157 "Empty entry not called correctly");
158
159 p.process_event(open_close());
160 BOOST_CHECK_MESSAGE(p.current_state()[0] == 2,"Open should be active"); //Open
161 BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(Empty)&>().get_attribute(exit_counter) == 1,
162 "Empty exit not called correctly");
163 BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(Open)&>().get_attribute(entry_counter) == 1,
164 "Open entry not called correctly");
165
166 p.process_event(open_close());
167 BOOST_CHECK_MESSAGE(p.current_state()[0] == 3,"Empty should be active"); //Empty
168 BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(Open)&>().get_attribute(exit_counter) == 1,
169 "Open exit not called correctly");
170 BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(Empty)&>().get_attribute(entry_counter) == 2,
171 "Empty entry not called correctly");
172 BOOST_CHECK_MESSAGE(p.get_attribute(can_close_drawer_counter) == 1,"guard not called correctly");
173
174 p.process_event(
175 cd_detected("louie, louie",DISK_DVD));
176 BOOST_CHECK_MESSAGE(p.current_state()[0] == 3,"Empty should be active"); //Empty
177 BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(Open)&>().get_attribute(exit_counter) == 1,
178 "Open exit not called correctly");
179 BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(Empty)&>().get_attribute(entry_counter) == 2,
180 "Empty entry not called correctly");
181
182 p.process_event(
183 cd_detected("louie, louie",DISK_CD));
184 BOOST_CHECK_MESSAGE(p.current_state()[0] == 4,"Playing should be active"); //Playing
185 BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(Empty)&>().get_attribute(exit_counter) == 2,
186 "Empty exit not called correctly");
187 BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(Stopped)&>().get_attribute(entry_counter) == 1,
188 "Stopped entry not called correctly");
189 BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(Stopped)&>().get_attribute(exit_counter) == 1,
190 "Stopped exit not called correctly");
191 BOOST_CHECK_MESSAGE(p.get_state<Playing_type&>().get_attribute(entry_counter) == 1,
192 "Playing entry not called correctly");
193 BOOST_CHECK_MESSAGE(p.get_attribute(start_playback_counter) == 1,"action not called correctly");
194 BOOST_CHECK_MESSAGE(p.get_attribute(test_fct_counter) == 1,"action not called correctly");
195
196 p.process_event(next_song);
197 BOOST_CHECK_MESSAGE(p.current_state()[0] == 4,"Playing should be active"); //Playing
198 BOOST_CHECK_MESSAGE(p.get_state<Playing_type&>().current_state()[0] == 1,"Song2 should be active");
199 BOOST_CHECK_MESSAGE(p.get_state<Playing_type&>().current_state()[1] == 3,"Region2State1 should be active");
200 BOOST_CHECK_MESSAGE(
201 p.get_state<Playing_type&>().get_state<BOOST_MSM_EUML_STATE_NAME(Region2State1)&>().get_attribute(entry_counter) == 1,
202 "Region2State1 entry not called correctly");
203 BOOST_CHECK_MESSAGE(
204 p.get_state<Playing_type&>().get_state<BOOST_MSM_EUML_STATE_NAME(Song2)&>().get_attribute(entry_counter) == 1,
205 "Song2 entry not called correctly");
206 BOOST_CHECK_MESSAGE(
207 p.get_state<Playing_type&>().get_state<BOOST_MSM_EUML_STATE_NAME(Song1)&>().get_attribute(exit_counter) == 1,
208 "Song1 exit not called correctly");
209 BOOST_CHECK_MESSAGE(
210 p.get_state<Playing_type&>().get_attribute(start_next_song_counter) == 0,
211 "submachine action not called correctly");
212
213 p.process_event(next_song);
214 BOOST_CHECK_MESSAGE(p.current_state()[0] == 4,"Playing should be active"); //Playing
215 BOOST_CHECK_MESSAGE(p.get_state<Playing_type&>().current_state()[0] == 2,"Song3 should be active");
216 BOOST_CHECK_MESSAGE(
217 p.get_state<Playing_type&>().get_state<BOOST_MSM_EUML_STATE_NAME(Song3)&>().get_attribute(entry_counter) == 1,
218 "Song3 entry not called correctly");
219 BOOST_CHECK_MESSAGE(
220 p.get_state<Playing_type&>().get_state<BOOST_MSM_EUML_STATE_NAME(Song2)&>().get_attribute(exit_counter) == 1,
221 "Song2 exit not called correctly");
222 BOOST_CHECK_MESSAGE(
223 p.get_state<Playing_type&>().get_attribute(start_next_song_counter) == 1,
224 "submachine action not called correctly");
225
226 p.process_event(previous_song);
227 BOOST_CHECK_MESSAGE(p.current_state()[0] == 4,"Playing should be active"); //Playing
228 BOOST_CHECK_MESSAGE(p.get_state<Playing_type&>().current_state()[0] == 1,"Song2 should be active");
229 BOOST_CHECK_MESSAGE(
230 p.get_state<Playing_type&>().get_state<BOOST_MSM_EUML_STATE_NAME(Song2)&>().get_attribute(entry_counter) == 2,
231 "Song2 entry not called correctly");
232 BOOST_CHECK_MESSAGE(
233 p.get_state<Playing_type&>().get_state<BOOST_MSM_EUML_STATE_NAME(Song3)&>().get_attribute(exit_counter) == 1,
234 "Song3 exit not called correctly");
235 BOOST_CHECK_MESSAGE(
236 p.get_state<Playing_type&>().get_attribute(start_prev_song_guard_counter) == 1,
237 "submachine guard not called correctly");
238 BOOST_CHECK_MESSAGE(
239 p.get_state<Playing_type&>().get_state<BOOST_MSM_EUML_STATE_NAME(Region2State2)&>().get_attribute(entry_counter) == 0,
240 "Region2State2 entry not called correctly");
241
242
243 p.process_event(pause());
244 BOOST_CHECK_MESSAGE(p.current_state()[0] == 1,"Paused should be active"); //Paused
245 BOOST_CHECK_MESSAGE(p.get_state<Playing_type&>().get_attribute(exit_counter) == 1,
246 "Playing exit not called correctly");
247 BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(Paused)&>().get_attribute(entry_counter) == 1,
248 "Paused entry not called correctly");
249
250 // go back to Playing
251 p.process_event(end_pause());
252 BOOST_CHECK_MESSAGE(p.current_state()[0] == 4,"Playing should be active"); //Playing
253 BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(Paused)&>().get_attribute(exit_counter) == 1,
254 "Paused exit not called correctly");
255 BOOST_CHECK_MESSAGE(p.get_state<Playing_type&>().get_attribute(entry_counter) == 2,
256 "Playing entry not called correctly");
257
258 p.process_event(pause());
259 BOOST_CHECK_MESSAGE(p.current_state()[0] == 1,"Paused should be active"); //Paused
260 BOOST_CHECK_MESSAGE(p.get_state<Playing_type&>().get_attribute(exit_counter) == 2,
261 "Playing exit not called correctly");
262 BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(Paused)&>().get_attribute(entry_counter) == 2,
263 "Paused entry not called correctly");
264
265 p.process_event(stop());
266 BOOST_CHECK_MESSAGE(p.current_state()[0] == 0,"Stopped should be active"); //Stopped
267 BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(Paused)&>().get_attribute(exit_counter) == 2,
268 "Paused exit not called correctly");
269 BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(Stopped)&>().get_attribute(entry_counter) == 2,
270 "Stopped entry not called correctly");
271
272 p.process_event(stop());
273 BOOST_CHECK_MESSAGE(p.current_state()[0] == 0,"Stopped should be active"); //Stopped
274 BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(Stopped)&>().get_attribute(exit_counter) == 2,
275 "Stopped exit not called correctly");
276 BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(Stopped)&>().get_attribute(entry_counter) == 3,
277 "Stopped entry not called correctly");
278 }
279 }
280