#include #include #include #include #include "secsgem/gem/ept_state.hpp" using namespace secsgem::gem; TEST_CASE("EPT: initial state is NonScheduledTime") { EptStateMachine ept; CHECK(ept.state() == EptState::NonScheduledTime); } TEST_CASE("EPT: every event transitions to exactly its target state") { EptStateMachine ept; CHECK(ept.on_event(EptEvent::EnterStandby)); CHECK(ept.state() == EptState::Standby); CHECK(ept.on_event(EptEvent::EnterProductive)); CHECK(ept.state() == EptState::Productive); CHECK(ept.on_event(EptEvent::EnterUnscheduledDown)); CHECK(ept.state() == EptState::UnscheduledDowntime); CHECK(ept.on_event(EptEvent::EnterEngineering)); CHECK(ept.state() == EptState::Engineering); CHECK(ept.on_event(EptEvent::EnterScheduledDown)); CHECK(ept.state() == EptState::ScheduledDowntime); CHECK(ept.on_event(EptEvent::EnterNonScheduled)); CHECK(ept.state() == EptState::NonScheduledTime); } TEST_CASE("EPT: change handler reports dwell time") { EptStateMachine ept; std::vector> transitions; ept.set_state_change_handler( [&](EptState, EptState to, EptEvent, std::chrono::milliseconds dwell) { transitions.emplace_back(to, dwell); }); std::this_thread::sleep_for(std::chrono::milliseconds(5)); ept.on_event(EptEvent::EnterStandby); std::this_thread::sleep_for(std::chrono::milliseconds(5)); ept.on_event(EptEvent::EnterProductive); REQUIRE(transitions.size() == 2); CHECK(transitions[0].first == EptState::Standby); CHECK(transitions[0].second.count() >= 1); // dwelled in NonScheduledTime CHECK(transitions[1].first == EptState::Productive); CHECK(transitions[1].second.count() >= 1); // dwelled in Standby } TEST_CASE("EPT: same-state event is a no-op (no handler call)") { EptStateMachine ept; ept.on_event(EptEvent::EnterStandby); int calls = 0; ept.set_state_change_handler( [&](EptState, EptState, EptEvent, std::chrono::milliseconds) { ++calls; }); CHECK(ept.on_event(EptEvent::EnterStandby)); // already in Standby CHECK(calls == 0); }