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/core/ignore_unused.hpp>
12
13#include <boost/msm/front/puml/puml.hpp>
14
15#ifndef BOOST_MSM_NONSTANDALONE_TEST
16#define BOOST_TEST_MODULE puml_test
17#endif
18#include <boost/test/unit_test.hpp>
19
20using namespace boost::msm::front;
21using namespace boost::msm::front::puml;
22
23namespace
24{
25
26 BOOST_AUTO_TEST_CASE( puml_test )
27 {
28 constexpr auto stt_ = R"([*]-> StateA
29 StateA -> StateB: evt1/ A2 [G1]
30 StateB -> StateB : evt1/ A1,A2 [G1]
31
32 StateB -> StateA: evt1)";
33 auto stt =
34 boost::msm::front::puml::create_transition_table([&]() {return stt_; });
35 static_assert(std::is_same_v<
36 decltype(stt),
37 boost::fusion::vector<
38 Row<State <by_name("StateA")>, Event <by_name("evt1")>, State <by_name("StateB")>, Action <by_name("A2")>, Guard <by_name("G1")> >,
39 Row<State <by_name("StateB")>, Event <by_name("evt1")>, State <by_name("StateB")>, ActionSequence_<boost::fusion::vector< Action<by_name("A1")>, Action<by_name("A2")>>>, Guard <by_name("G1")> >,
40 Row<State <by_name("StateB")>, Event <by_name("evt1")>, State <by_name("StateA")>, none, none >
41 >
42 >);
43
44 constexpr auto stt2_ = R"([*]->StateA
45 StateA -> StateB: evt1/ A2 [G1&&G2]
46 StateB -> StateB : evt1/ A1, defer [G1]
47
48 StateB -> StateA: evt1)";
49 auto stt2 =
50 boost::msm::front::puml::create_transition_table([&]() {return stt2_; });
51 static_assert(std::is_same_v<
52 decltype(stt2),
53 boost::fusion::vector<
54 Row<State <by_name("StateA")>, Event <by_name("evt1")>, State <by_name("StateB")>, Action <by_name("A2")>, And_<Guard <by_name("G1")>, Guard <by_name("G2")>> >,
55 Row<State <by_name("StateB")>, Event <by_name("evt1")>, State <by_name("StateB")>, ActionSequence_<boost::fusion::vector< Action<by_name("A1")>, Defer>>, Guard <by_name("G1")> >,
56 Row<State <by_name("StateB")>, Event <by_name("evt1")>, State <by_name("StateA")>, none, none >
57 >
58 >);
59
60 constexpr auto stt3_ = R"(StateA -> StateB: evt1/ A2 [G1 && G2 && G3])";
61 auto stt3 =
62 boost::msm::front::puml::create_transition_table([&]() {return stt3_; });
63 static_assert(std::is_same_v<
64 decltype(stt3),
65 boost::fusion::vector<
66 Row<State <by_name("StateA")>, Event <by_name("evt1")>, State <by_name("StateB")>, Action <by_name("A2")>, And_<Guard <by_name("G1")>, And_<Guard <by_name("G2")>, Guard <by_name("G3")>>> >
67 >
68 >);
69
70 constexpr auto stt4_ = R"(StateA -> StateB: evt1/ A2 [G1 || G2])";
71 auto stt4 =
72 boost::msm::front::puml::create_transition_table([&]() {return stt4_; });
73 static_assert(std::is_same_v<
74 decltype(stt4),
75 boost::fusion::vector<
76 Row<State <by_name("StateA")>, Event <by_name("evt1")>, State <by_name("StateB")>, Action <by_name("A2")>, Or_<Guard <by_name("G1")>, Guard <by_name("G2")>> >
77 >
78 >);
79
80 constexpr auto stt5_ = R"(StateA -> StateB: evt1/ A2 [G1 && G2 || G3])";
81 auto stt5 =
82 boost::msm::front::puml::create_transition_table([&]() {return stt5_; });
83 static_assert(std::is_same_v<
84 decltype(stt5),
85 boost::fusion::vector<
86 Row<State <by_name("StateA")>, Event <by_name("evt1")>, State <by_name("StateB")>, Action <by_name("A2")>, Or_<And_<Guard <by_name("G1")>, Guard <by_name("G2")>>, Guard <by_name("G3")>> >
87 >
88 >);
89
90 constexpr auto stt6_ = R"(StateA ---> StateB: evt1/ A2 [!G1])";
91 auto stt6 =
92 boost::msm::front::puml::create_transition_table([&]() {return stt6_; });
93 static_assert(std::is_same_v<
94 decltype(stt6),
95 boost::fusion::vector<
96 Row<State <by_name("StateA")>, Event <by_name("evt1")>, State <by_name("StateB")>, Action <by_name("A2")>, Not_<Guard <by_name("G1")>> >
97 >
98 >);
99
100 constexpr auto stt7_ = R"(StateA -> StateB: evt1/ A2 [G1 || !G2])";
101 auto stt7 =
102 boost::msm::front::puml::create_transition_table([&]() {return stt7_; });
103 static_assert(std::is_same_v<
104 decltype(stt7),
105 boost::fusion::vector<
106 Row<State <by_name("StateA")>, Event <by_name("evt1")>, State <by_name("StateB")>, Action <by_name("A2")>, Or_<Guard <by_name("G1")>, Not_<Guard <by_name("G2")>>> >
107 >
108 >);
109
110 constexpr auto stt8_ = R"(StateA -> StateB: evt1/ A2 [Or(G1,Not(G2))])";
111 auto stt8 =
112 boost::msm::front::puml::create_transition_table([&]() {return stt8_; });
113 static_assert(std::is_same_v<
114 decltype(stt8),
115 boost::fusion::vector<
116 Row<State <by_name("StateA")>, Event <by_name("evt1")>, State <by_name("StateB")>, Action <by_name("A2")>, Or_<Guard <by_name("G1")>, Not_<Guard <by_name("G2")>>> >
117 >
118 >);
119
120 auto stt9 =
121 boost::msm::front::puml::create_transition_table([]() {return R"(StateA -> StateB: evt1/ A2 [(G1 || G2) && G3])"; });
122 static_assert(std::is_same_v<
123 decltype(stt9),
124 boost::fusion::vector<
125 Row<State <by_name("StateA")>, Event <by_name("evt1")>, State <by_name("StateB")>, Action <by_name("A2")>, And_<Or_<Guard <by_name("G1")>, Guard <by_name("G2")>>, Guard <by_name("G3")>> >
126 >
127 >);
128
129 auto stt10 =
130 boost::msm::front::puml::create_transition_table([]() {return R"(StateA -> StateB: evt1/ A2 [(G1 && G2) || G3])"; });
131 static_assert(std::is_same_v<
132 decltype(stt10),
133 boost::fusion::vector<
134 Row<State <by_name("StateA")>, Event <by_name("evt1")>, State <by_name("StateB")>, Action <by_name("A2")>, Or_<And_<Guard <by_name("G1")>, Guard <by_name("G2")>>, Guard <by_name("G3")>> >
135 >
136 >);
137
138 auto stt11 =
139 boost::msm::front::puml::create_transition_table([]() {return R"(StateA -> StateB: evt1/ A2 [G3 && ( G1 || G2 )])"; });
140 static_assert(std::is_same_v<
141 decltype(stt11),
142 boost::fusion::vector<
143 Row<State <by_name("StateA")>, Event <by_name("evt1")>, State <by_name("StateB")>, Action <by_name("A2")>, And_<Guard <by_name("G3")>, Or_<Guard <by_name("G1")>, Guard <by_name("G2")>>> >
144 >
145 >);
146
147 auto stt12 =
148 boost::msm::front::puml::create_transition_table([]() {return R"(StateA -> StateB: evt1/ A2 [G3 || ( G1 && G2 )])"; });
149 static_assert(std::is_same_v<
150 decltype(stt12),
151 boost::fusion::vector<
152 Row<State <by_name("StateA")>, Event <by_name("evt1")>, State <by_name("StateB")>, Action <by_name("A2")>, Or_<Guard <by_name("G3")>, And_<Guard <by_name("G1")>, Guard <by_name("G2")>>> >
153 >
154 >);
155
156 auto stt13 =
157 boost::msm::front::puml::create_transition_table([]() {return R"(StateA -> StateB: evt1/ A2 [!( G1 && G2 )])"; });
158 static_assert(std::is_same_v<
159 decltype(stt13),
160 boost::fusion::vector<
161 Row<State <by_name("StateA")>, Event <by_name("evt1")>, State <by_name("StateB")>, Action <by_name("A2")>, Not_<And_<Guard <by_name("G1")>, Guard <by_name("G2")>>> >
162 >
163 >);
164
165 auto stt14 =
166 boost::msm::front::puml::create_transition_table([]() {return R"(StateA -> StateB: evt1/ A2 [G3 || !( G1 && G2 )])"; });
167 static_assert(std::is_same_v<
168 decltype(stt14),
169 boost::fusion::vector<
170 Row<State <by_name("StateA")>, Event <by_name("evt1")>, State <by_name("StateB")>, Action <by_name("A2")>, Or_<Guard <by_name("G3")>, Not_<And_<Guard <by_name("G1")>, Guard <by_name("G2")>>>> >
171 >
172 >);
173
174 auto stt15 =
175 boost::msm::front::puml::create_transition_table([]() {return R"(StateA -> StateB: evt1/ A2 [(G3 && G1) || ( G1 && G2 )])"; });
176 static_assert(std::is_same_v<
177 decltype(stt15),
178 boost::fusion::vector<
179 Row<State <by_name("StateA")>, Event <by_name("evt1")>, State <by_name("StateB")>, Action <by_name("A2")>,
180 Or_<And_<Guard <by_name("G3")>, Guard <by_name("G1")>>, And_<Guard <by_name("G1")>, Guard <by_name("G2")>>> >
181 >
182 >);
183
184 auto stt16 =
185 boost::msm::front::puml::create_transition_table([]() {return R"(StateA -> StateB: evt1/ A2 [(G3 && G1) || !(G1 && G2)])"; });
186 static_assert(std::is_same_v<
187 decltype(stt16),
188 boost::fusion::vector<
189 Row<State <by_name("StateA")>, Event <by_name("evt1")>, State <by_name("StateB")>, Action <by_name("A2")>,
190 Or_<And_<Guard <by_name("G3")>, Guard <by_name("G1")>>, Not_<And_<Guard <by_name("G1")>, Guard <by_name("G2")>>>> >
191 >
192 >);
193
194 // internal detail::Transition
195 auto stt17 =
196 boost::msm::front::puml::create_transition_table([]() {return R"(StateA -> StateA: -evt1/ A2 [G1])"; });
197 static_assert(std::is_same_v<
198 decltype(stt17),
199 boost::fusion::vector<
200 Row<State <by_name("StateA")>, Event <by_name("evt1")>, none, Action <by_name("A2")>, Guard <by_name("G1")>>
201 >
202 >);
203
204 // kleene
205 auto stt18 =
206 boost::msm::front::puml::create_transition_table([]() {return R"(StateA -> StateA: * / A2 [G1])"; });
207 static_assert(std::is_same_v<
208 decltype(stt18),
209 boost::fusion::vector<
210 Row<State <by_name("StateA")>, boost::any, State <by_name("StateA")>, Action <by_name("A2")>, Guard <by_name("G1")>>
211 >
212 >);
213
214 // internal + kleene
215 auto stt19 =
216 boost::msm::front::puml::create_transition_table([]() {return R"(StateA -> StateA: -* / A2 [G1])"; });
217 static_assert(std::is_same_v<
218 decltype(stt19),
219 boost::fusion::vector<
220 Row<State <by_name("StateA")>, boost::any, none, Action <by_name("A2")>, Guard <by_name("G1")>>
221 >
222 >);
223
224 // test init states
225 static_assert(std::is_same_v<
226 decltype(boost::msm::front::puml::create_transition_table([]() {return R"([*] -> StateA
227 StateA --> StateA: evt1 / defer)"; })),
228 boost::fusion::vector<
229 Row<State <by_name("StateA")>, Event <by_name("evt1")>, State <by_name("StateA")>, Defer, none >
230 >
231 > );
232
233
234 State< by_name(str: "StateXXX")> s1;
235 boost::ignore_unused(s1);
236
237 // initial states
238 constexpr auto stt9_ = R"(
239 [*] --> StateA
240 StateA -> StateB: evt1 [G1]
241 StateB -> StateB : evt1 / A1 [G1]
242 --
243 [*]->StateC
244 StateC -> StateD: -*)";
245 auto inits =
246 create_initial_states(stt_func: [&]() {return stt9_; });
247 static_assert(std::is_same_v<
248 decltype(inits),
249 boost::fusion::vector< State <by_name(str: "StateA")>, State <by_name(str: "StateC")>>
250 >);
251
252 //constexpr auto name_ = "StateA";
253 //std::cout << typeid(boost::msm::front::puml::detail::parse_flags(stt_, name_)).name() << std::endl;
254 }
255}
256
257

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