File indexing completed on 2025-10-31 08:18:12
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 }