1 | // Copyright 2024 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 <boost/msm/front/puml/puml.hpp> |
12 | |
13 | #ifndef BOOST_MSM_NONSTANDALONE_TEST |
14 | #define BOOST_TEST_MODULE puml_test_2 |
15 | #endif |
16 | #include <boost/test/unit_test.hpp> |
17 | |
18 | using namespace boost::msm::front; |
19 | using namespace boost::msm::front::puml; |
20 | |
21 | namespace |
22 | { |
23 | |
24 | BOOST_AUTO_TEST_CASE( puml_test_2 ) |
25 | { |
26 | constexpr auto stt20_ = R"([*]-> StateA |
27 | StateA -> StateB: evt1/ A2 [G1] |
28 | StateA : flag F1 |
29 | StateA -> StateC: evt2/ A2 [G1])" ; |
30 | auto stt20 = |
31 | boost::msm::front::puml::create_transition_table([&]() {return stt20_; }); |
32 | static_assert(std::is_same_v< |
33 | decltype(stt20), |
34 | boost::fusion::vector< |
35 | Row<State <by_name("StateA" ), boost::fusion::vector<Flag<by_name("F1" )>>>, |
36 | Event <by_name("evt1" )>, |
37 | State <by_name("StateB" )>, |
38 | Action <by_name("A2" )>, |
39 | Guard <by_name("G1" )> >, |
40 | Row<State <by_name("StateA" ), boost::fusion::vector<Flag<by_name("F1" )>>>, |
41 | Event <by_name("evt2" )>, |
42 | State <by_name("StateC" )>, |
43 | Action <by_name("A2" )>, |
44 | Guard <by_name("G1" )> > |
45 | > |
46 | >); |
47 | |
48 | constexpr auto stt21_ = R"([*]-> StateA |
49 | StateA -> StateB: evt1/ A2 [G1] |
50 | StateA : flag F1 |
51 | StateA : flag F2)" ; |
52 | auto stt21 = |
53 | boost::msm::front::puml::create_transition_table([&]() {return stt21_; }); |
54 | static_assert(std::is_same_v< |
55 | decltype(stt21), |
56 | boost::fusion::vector< |
57 | Row<State <by_name("StateA" ), boost::fusion::vector<Flag<by_name("F1" )>, Flag<by_name("F2" )>>>, |
58 | Event <by_name("evt1" )>, |
59 | State <by_name("StateB" )>, |
60 | Action <by_name("A2" )>, |
61 | Guard <by_name("G1" )> > |
62 | > |
63 | >); |
64 | |
65 | constexpr auto stt22_ = R"([*]-> StateA |
66 | StateA -> StateB: evt1/ A2 [G1] |
67 | StateA : flag F1 |
68 | StateB : flag F2)" ; |
69 | auto stt22 = |
70 | boost::msm::front::puml::create_transition_table([&]() {return stt22_; }); |
71 | static_assert(std::is_same_v< |
72 | decltype(stt22), |
73 | boost::fusion::vector< |
74 | Row<State <by_name("StateA" ), boost::fusion::vector<Flag<by_name("F1" )>>>, |
75 | Event <by_name("evt1" )>, |
76 | State <by_name("StateB" ), boost::fusion::vector<Flag<by_name("F2" )>>>, |
77 | Action <by_name("A2" )>, |
78 | Guard <by_name("G1" )> > |
79 | > |
80 | >); |
81 | |
82 | constexpr auto stt23_ = R"([*]-> StateA |
83 | StateA -> StateB: evt1/ A2 [G1] |
84 | StateA : flag F1 |
85 | StateA : flag F2 |
86 | StateB : flag F2)" ; |
87 | auto stt23 = |
88 | boost::msm::front::puml::create_transition_table([&]() {return stt23_; }); |
89 | static_assert(std::is_same_v< |
90 | decltype(stt23), |
91 | boost::fusion::vector< |
92 | Row<State <by_name("StateA" ), boost::fusion::vector<Flag<by_name("F1" )>, Flag<by_name("F2" )>>>, |
93 | Event <by_name("evt1" )>, |
94 | State <by_name("StateB" ), boost::fusion::vector<Flag<by_name("F2" )>>>, |
95 | Action <by_name("A2" )>, |
96 | Guard <by_name("G1" )> > |
97 | > |
98 | >); |
99 | |
100 | constexpr auto stt24_ = R"([*]-> StateA |
101 | StateA -> StateB: evt1/ A2 [G1] |
102 | StateA : entry A1 |
103 | StateA : entry A2 |
104 | StateB : entry A1 |
105 | )" ; |
106 | auto stt24 = |
107 | boost::msm::front::puml::create_transition_table([&]() {return stt24_; }); |
108 | |
109 | static_assert(std::is_same_v< |
110 | decltype(stt24), |
111 | boost::fusion::vector< |
112 | Row< |
113 | State < by_name("StateA" ), |
114 | boost::fusion::vector<>, |
115 | boost::fusion::vector< |
116 | boost::msm::front::puml::detail::pair_type < |
117 | Action<by_name("A1" )>, |
118 | none |
119 | >, |
120 | boost::msm::front::puml::detail::pair_type < |
121 | Action<by_name("A2" )>, |
122 | none |
123 | > |
124 | > |
125 | >, |
126 | Event <by_name("evt1" )>, |
127 | State < by_name("StateB" ), |
128 | boost::fusion::vector<>, |
129 | boost::fusion::vector< |
130 | boost::msm::front::puml::detail::pair_type < |
131 | Action<by_name("A1" )>, |
132 | none |
133 | > |
134 | >>, |
135 | Action <by_name("A2" )>, |
136 | Guard <by_name("G1" )> > |
137 | > |
138 | >); |
139 | |
140 | constexpr auto stt25_ = R"([*]-> StateA |
141 | StateA -> StateB: evt1/ A2 [G1] |
142 | StateA : entry A1 [G1] |
143 | StateA : entry A2 |
144 | StateB : entry A1 [G1] |
145 | StateB : entry A2 |
146 | )" ; |
147 | auto stt25 = |
148 | boost::msm::front::puml::create_transition_table([&]() {return stt25_; }); |
149 | |
150 | static_assert(std::is_same_v< |
151 | decltype(stt25), |
152 | boost::fusion::vector< |
153 | Row< |
154 | State < by_name("StateA" ), |
155 | boost::fusion::vector<>, |
156 | boost::fusion::vector< |
157 | boost::msm::front::puml::detail::pair_type < |
158 | Action<by_name("A1" )>, |
159 | Guard<by_name("G1" )> |
160 | >, |
161 | boost::msm::front::puml::detail::pair_type < |
162 | Action<by_name("A2" )>, |
163 | none |
164 | > |
165 | > |
166 | >, |
167 | Event <by_name("evt1" )>, |
168 | State < by_name("StateB" ), |
169 | boost::fusion::vector<>, |
170 | boost::fusion::vector< |
171 | boost::msm::front::puml::detail::pair_type < |
172 | Action<by_name("A1" )>, |
173 | Guard<by_name("G1" )> |
174 | >, |
175 | boost::msm::front::puml::detail::pair_type < |
176 | Action<by_name("A2" )>, |
177 | none |
178 | > |
179 | > |
180 | >, |
181 | Action <by_name("A2" )>, |
182 | Guard <by_name("G1" )> > |
183 | > |
184 | >); |
185 | |
186 | constexpr auto stt26_ = R"([*]-> StateA |
187 | StateA -> StateB: evt1/ A2 [G1] |
188 | StateA : entry A1,A2 [G1 && G2] |
189 | StateB : entry A1,A2 [G1&&G2])" ; |
190 | auto stt26 = |
191 | boost::msm::front::puml::create_transition_table([&]() {return stt26_; }); |
192 | |
193 | static_assert(std::is_same_v< |
194 | decltype(stt26), |
195 | boost::fusion::vector< |
196 | Row< |
197 | State < by_name("StateA" ), |
198 | boost::fusion::vector<>, |
199 | boost::fusion::vector< |
200 | boost::msm::front::puml::detail::pair_type < |
201 | boost::msm::front::ActionSequence_< boost::fusion::vector< |
202 | Action<by_name("A1" )>, Action<by_name("A2" )> |
203 | >>, |
204 | And_<Guard <by_name("G1" )>, Guard <by_name("G2" )>> |
205 | > |
206 | > |
207 | >, |
208 | Event <by_name("evt1" )>, |
209 | State < by_name("StateB" ), |
210 | boost::fusion::vector<>, |
211 | boost::fusion::vector< |
212 | boost::msm::front::puml::detail::pair_type < |
213 | boost::msm::front::ActionSequence_< boost::fusion::vector< |
214 | Action<by_name("A1" )>, Action<by_name("A2" )> |
215 | >>, |
216 | And_<Guard <by_name("G1" )>, Guard <by_name("G2" )>> |
217 | > |
218 | > |
219 | >, |
220 | Action <by_name("A2" )>, |
221 | Guard <by_name("G1" )> > |
222 | > |
223 | >); |
224 | |
225 | constexpr auto stt27_ = R"([*]-> StateA |
226 | StateA -> StateB: evt1/ A2 [G1] |
227 | StateA : exit A1,A2 [G1 && G2] |
228 | StateB : entry A1,A2 [G1&&G2])" ; |
229 | auto stt27 = |
230 | boost::msm::front::puml::create_transition_table([&]() {return stt27_; }); |
231 | |
232 | static_assert(std::is_same_v< |
233 | decltype(stt27), |
234 | boost::fusion::vector< |
235 | Row< |
236 | State < by_name("StateA" ), |
237 | boost::fusion::vector<>, |
238 | boost::fusion::vector<>, |
239 | boost::fusion::vector< |
240 | boost::msm::front::puml::detail::pair_type < |
241 | boost::msm::front::ActionSequence_< boost::fusion::vector< |
242 | Action<by_name("A1" )>, Action<by_name("A2" )> |
243 | >>, |
244 | And_<Guard <by_name("G1" )>, Guard <by_name("G2" )>> |
245 | > |
246 | > |
247 | >, |
248 | Event <by_name("evt1" )>, |
249 | State < by_name("StateB" ), |
250 | boost::fusion::vector<>, |
251 | boost::fusion::vector< |
252 | boost::msm::front::puml::detail::pair_type < |
253 | boost::msm::front::ActionSequence_< boost::fusion::vector< |
254 | Action<by_name("A1" )>, Action<by_name("A2" )> |
255 | >>, |
256 | And_<Guard <by_name("G1" )>, Guard <by_name("G2" )>> |
257 | > |
258 | > |
259 | >, |
260 | Action <by_name("A2" )>, |
261 | Guard <by_name("G1" )> > |
262 | > |
263 | >); |
264 | |
265 | constexpr auto stt28_ = R"([*]-> StateA |
266 | StateA -> StateB: evt1/ A2 [G1] |
267 | StateB -> [*])" ; |
268 | auto stt28 = |
269 | boost::msm::front::puml::create_transition_table([&]() {return stt28_; }); |
270 | static_assert(std::is_same_v< |
271 | decltype(stt28), |
272 | boost::fusion::vector< |
273 | Row<State <by_name("StateA" )>, |
274 | Event <by_name("evt1" )>, |
275 | State <by_name("StateB" ), boost::fusion::vector<boost::msm::TerminateFlag>>, |
276 | Action <by_name("A2" )>, |
277 | Guard <by_name("G1" )> > |
278 | > |
279 | >); |
280 | |
281 | |
282 | constexpr auto stt29_ = R"( |
283 | @startuml Player |
284 | skinparam linetype polyline |
285 | state Player{ |
286 | [*]-> StateA |
287 | StateA -> StateB: evt1/ A2 [G1] |
288 | -- |
289 | [*]-> StateC |
290 | StateC -> TerminalState : terminate_event |
291 | TerminalState -> [*] |
292 | } |
293 | @enduml |
294 | )" ; |
295 | auto stt29 = |
296 | boost::msm::front::puml::create_transition_table([&]() {return stt29_; }); |
297 | static_assert(std::is_same_v< |
298 | decltype(stt29), |
299 | boost::fusion::vector< |
300 | Row<State <by_name("StateA" )>, |
301 | Event <by_name("evt1" )>, |
302 | State <by_name("StateB" )>, |
303 | Action <by_name("A2" )>, |
304 | Guard <by_name("G1" )> >, |
305 | Row<State <by_name("StateC" )>, |
306 | Event <by_name("terminate_event" )>, |
307 | State <by_name("TerminalState" ), boost::fusion::vector<boost::msm::TerminateFlag>>, |
308 | none, |
309 | none> |
310 | > |
311 | >); |
312 | static_assert(boost::msm::front::puml::detail::count_terminates(s: stt29_) == 1); |
313 | static_assert(boost::msm::front::puml::detail::count_inits(s: stt29_) == 2); |
314 | |
315 | //std::cout << "dbg1:" << typeid(stt25).name() << std::endl << std::endl; |
316 | //std::cout << "dbg2:" << typeid(stt29).name() << std::endl << std::endl; |
317 | } |
318 | } |
319 | |
320 | |