File indexing completed on 2025-12-16 09:25:17
0001
0002
0003
0004
0005
0006
0007
0008
0009 #include <boost/test/unit_test.hpp>
0010
0011 #include "Acts/Utilities/FiniteStateMachine.hpp"
0012
0013 #include <iostream>
0014 #include <optional>
0015 #include <stdexcept>
0016
0017 using namespace Acts;
0018
0019 namespace ActsTests {
0020
0021 namespace states {
0022 struct Disconnected {};
0023
0024 struct Connecting {};
0025 struct Pinging {};
0026 struct Connected {};
0027 }
0028
0029 namespace events {
0030 struct Connect {};
0031 struct Established {};
0032 struct Timeout {};
0033 struct Ping {};
0034 struct Pong {};
0035 struct Disconnect {};
0036 }
0037
0038 struct fsm : FiniteStateMachine<fsm, states::Disconnected, states::Connecting,
0039 states::Pinging, states::Connected> {
0040 fsm() : fsm_base(states::Disconnected{}) {}
0041
0042 event_return on_event(const states::Disconnected& ,
0043 const events::Connect& ) {
0044 return states::Connecting{};
0045 }
0046
0047 event_return on_event(const states::Connecting& ,
0048 const events::Established& ) {
0049 return states::Connected{};
0050 }
0051
0052 event_return on_event(const states::Connected& ,
0053 const events::Ping& ) {
0054 std::cout << "ping!" << std::endl;
0055 setState(states::Pinging{});
0056 return process_event(events::Pong{});
0057 }
0058
0059 event_return on_event(const states::Pinging& ,
0060 const events::Pong& ) {
0061 std::cout << "pong!" << std::endl;
0062 return states::Connected{};
0063 }
0064
0065 event_return on_event(const states::Connected& ,
0066 const events::Timeout& ) {
0067 return states::Connecting{};
0068 }
0069
0070 event_return on_event(const states::Connected& ,
0071 const events::Disconnect& ) {
0072 return states::Disconnected{};
0073 }
0074
0075 template <typename State, typename Event>
0076 event_return on_event(const State& ,
0077 const Event& ) const {
0078 return Terminated{};
0079 }
0080
0081 template <typename State, typename... Args>
0082 void on_enter(const State& , Args&&... ) {}
0083
0084 template <typename State, typename... Args>
0085 void on_exit(const State& , Args&&... ) {}
0086
0087 template <typename... Args>
0088 void on_process(Args&&... ) {}
0089 };
0090
0091 BOOST_AUTO_TEST_SUITE(UtilitiesSuite)
0092
0093 BOOST_AUTO_TEST_CASE(Transitions) {
0094 fsm sm{};
0095 BOOST_CHECK(sm.is(states::Disconnected{}));
0096 sm.dispatch(events::Connect{});
0097 BOOST_CHECK(sm.is(states::Connecting{}));
0098 sm.dispatch(events::Established{});
0099 BOOST_CHECK(sm.is(states::Connected{}));
0100 sm.dispatch(events::Ping{});
0101 sm.dispatch(events::Ping{});
0102 sm.dispatch(events::Ping{});
0103 sm.dispatch(events::Ping{});
0104 BOOST_CHECK(sm.is(states::Connected{}));
0105 sm.dispatch(events::Timeout{});
0106 BOOST_CHECK(sm.is(states::Connecting{}));
0107 sm.dispatch(events::Established{});
0108 BOOST_CHECK(sm.is(states::Connected{}));
0109 sm.dispatch(events::Disconnect{});
0110 BOOST_CHECK(sm.is(states::Disconnected{}));
0111 }
0112
0113 BOOST_AUTO_TEST_CASE(Terminted) {
0114 fsm sm{};
0115 BOOST_CHECK(sm.is(states::Disconnected{}));
0116
0117 sm.dispatch(events::Disconnect{});
0118 BOOST_CHECK(sm.terminated());
0119 }
0120
0121 struct fsm2
0122 : FiniteStateMachine<fsm2, states::Disconnected, states::Connected> {
0123 fsm2() : fsm_base(states::Disconnected{}) {}
0124
0125 event_return on_event(const states::Disconnected& ,
0126 const events::Connect& , double f) {
0127 std::cout << "f: " << f << std::endl;
0128 return states::Connected{};
0129 }
0130
0131 event_return on_event(const states::Connected& ,
0132 const events::Disconnect& ) {
0133 std::cout << "disconnect!" << std::endl;
0134 return states::Disconnected{};
0135 }
0136
0137 template <typename State, typename Event, typename... Args>
0138 event_return on_event(const State& , const Event& ,
0139 Args&&... ) const {
0140 return Terminated{};
0141 }
0142
0143 template <typename... Args>
0144 void on_enter(const Terminated& , Args&&... ) {
0145 throw std::runtime_error("FSM terminated!");
0146 }
0147
0148 template <typename State, typename... Args>
0149 void on_enter(const State& , Args&&... ) {}
0150
0151 template <typename State, typename... Args>
0152 void on_exit(const State& , Args&&... ) {}
0153 template <typename... Args>
0154 void on_process(Args&&... ) {}
0155 };
0156
0157 BOOST_AUTO_TEST_CASE(Arguments) {
0158 fsm2 sm{};
0159 BOOST_CHECK(sm.is(states::Disconnected{}));
0160
0161 sm.dispatch(events::Connect{}, 42.);
0162 BOOST_CHECK(sm.is(states::Connected{}));
0163 sm.dispatch(events::Disconnect{});
0164 BOOST_CHECK(sm.is(states::Disconnected{}));
0165 sm.dispatch(events::Connect{}, -1.);
0166
0167
0168 BOOST_REQUIRE_THROW(sm.dispatch(events::Disconnect{}, 9), std::runtime_error);
0169 BOOST_CHECK(sm.terminated());
0170
0171
0172
0173 BOOST_REQUIRE_THROW(sm.dispatch(events::Connect{}), std::runtime_error);
0174
0175 BOOST_CHECK(sm.terminated());
0176
0177
0178 sm.setState(states::Disconnected{});
0179 BOOST_CHECK(sm.is(states::Disconnected{}));
0180 sm.dispatch(events::Connect{}, -1.);
0181 BOOST_CHECK(sm.is(states::Connected{}));
0182 }
0183
0184 struct S1 {};
0185 struct S2 {};
0186 struct S3 {};
0187
0188 struct E1 {};
0189 struct E2 {};
0190 struct E3 {};
0191
0192 struct fsm3 : FiniteStateMachine<fsm3, S1, S2, S3> {
0193 bool on_exit_called = false;
0194 bool on_enter_called = false;
0195 bool on_process_called = false;
0196 void reset() {
0197 on_exit_called = false;
0198 on_enter_called = false;
0199 on_process_called = false;
0200 }
0201
0202
0203 event_return on_event(const S1& , const E1& ) {
0204 return S2{};
0205 }
0206
0207
0208
0209 event_return on_event(const S2& , const E1& ) {
0210 return S2{};
0211 }
0212
0213
0214
0215 event_return on_event(const S2& , const E2& ) {
0216 return std::nullopt;
0217
0218 }
0219
0220
0221
0222 event_return on_event(const S2& , const E3& ) {
0223 return S3{};
0224 }
0225
0226
0227
0228 template <typename State, typename Event, typename... Args>
0229 event_return on_event(const State& , const Event& ,
0230 Args&&... ) const {
0231 return Terminated{};
0232 }
0233
0234 template <typename State, typename... Args>
0235 void on_enter(const State& , Args&&... ) {
0236 on_enter_called = true;
0237 }
0238
0239 template <typename State, typename... Args>
0240 void on_exit(const State& , Args&&... ) {
0241 on_exit_called = true;
0242 }
0243
0244 template <typename... Args>
0245 void on_process(Args&&... ) {
0246 on_process_called = true;
0247 }
0248 };
0249
0250 BOOST_AUTO_TEST_CASE(InternalTransitions) {
0251 fsm3 sm;
0252 BOOST_CHECK(sm.is(S1{}));
0253
0254 sm.dispatch(E1{});
0255 BOOST_CHECK(sm.is(S2{}));
0256 BOOST_CHECK(sm.on_exit_called);
0257 BOOST_CHECK(sm.on_enter_called);
0258 BOOST_CHECK(sm.on_process_called);
0259
0260 sm.reset();
0261
0262 sm.dispatch(E1{});
0263
0264 BOOST_CHECK(sm.is(S2{}));
0265
0266 BOOST_CHECK(sm.on_exit_called);
0267 BOOST_CHECK(sm.on_enter_called);
0268 BOOST_CHECK(sm.on_process_called);
0269 sm.reset();
0270
0271 sm.dispatch(E2{});
0272
0273 BOOST_CHECK(sm.is(S2{}));
0274
0275 BOOST_CHECK(!sm.on_exit_called);
0276 BOOST_CHECK(!sm.on_enter_called);
0277 BOOST_CHECK(sm.on_process_called);
0278 sm.reset();
0279
0280 sm.dispatch(E3{});
0281 BOOST_CHECK(sm.is(S3{}));
0282
0283 BOOST_CHECK(sm.on_exit_called);
0284 BOOST_CHECK(sm.on_enter_called);
0285 BOOST_CHECK(sm.on_process_called);
0286
0287 sm.setState(S1{});
0288 sm.reset();
0289 BOOST_CHECK(sm.is(S1{}));
0290
0291 sm.dispatch(E3{});
0292
0293 BOOST_CHECK(sm.terminated());
0294
0295 BOOST_CHECK(sm.on_exit_called);
0296 BOOST_CHECK(sm.on_enter_called);
0297 BOOST_CHECK(sm.on_process_called);
0298 }
0299
0300 BOOST_AUTO_TEST_SUITE_END()
0301
0302 }