STAR
Cal STAR — firmware, DAQ server, and engine design
Loading...
Searching...
No Matches
test_actuator_state_machine.cpp
Go to the documentation of this file.
1/**
2 * Actuator state machine unit tests
3 *
4 * Tests the actuator applyPacketTransition() and getBoardStateForHeartbeat()
5 * functions. Because these are static in Actuator_Hotfire/main.cpp with tightly
6 * coupled globals, we extract the pure logic here for testing.
7 */
8#include <unity.h>
9
10#include <cstring>
11#include <set>
12#include <vector>
13
14// DAQv2-Comms
15#include "DiabloEnums.h"
16#include "DiabloPacketUtils.cpp"
17#include "DiabloPacketUtils.h"
18#include "DiabloPackets.h"
19
20// ---------------------------------------------------------------------------
21// Replicate the actuator state machine enums and transition logic
22// (extracted from Actuator_Hotfire/src/main.cpp for testability)
23// ---------------------------------------------------------------------------
24
35
46
47// Replicate getBoardStateForHeartbeat() from Actuator_Hotfire/main.cpp
71
72// Replicate applyPacketTransition() from Actuator_Hotfire/main.cpp
73// Takes state + is_abort_controller as explicit params instead of globals
76 bool is_abort_controller, bool enable_transitions) {
77 // Global Clear Abort recovery
81 }
82 }
83
84 switch (state) {
86 if (kind == IncomingPacketKind::Config) {
88 }
89 break;
91 // Stay in Active: no transitions on Abort, AbortDone, or
92 // NoConnAbort (unless config allows).
93 if (enable_transitions) {
94 if (kind == IncomingPacketKind::Abort ||
97 } else if (kind == IncomingPacketKind::NoConnAbort &&
100 }
101 }
102 break;
106 }
107 break;
108 default:
109 break;
110 }
111 return state;
112}
113
114// ===========================================================================
115// Packet-driven transition tests
116// ===========================================================================
117
124
132
139
146
148 // With transitions disabled, Active -> Abort returns Active
150 IncomingPacketKind::Abort, true, false);
151 TEST_ASSERT_EQUAL((int)ActuatorControllerState::Active, (int)result);
152}
153
155 // With transitions ENABLED, Active -> Abort goes to AbortFinished
157 IncomingPacketKind::Abort, true, true);
158 TEST_ASSERT_EQUAL((int)ActuatorControllerState::AbortFinished, (int)result);
159}
160
167
174
176 // When disabled, NoConnAbort does not transition
177 auto result =
179 IncomingPacketKind::NoConnAbort, false, false);
180 TEST_ASSERT_EQUAL((int)ActuatorControllerState::Active, (int)result);
181}
182
184 // When ENABLED, NoConnAbort (as a non-controller) goes to
185 // NoConnAbortFollower
186 auto result =
190 (int)result);
191}
192
194 // ClearAbort only transitions from AbortFinished, not NoConnectionAbort
195 auto result =
197 IncomingPacketKind::ClearAbort, true, false);
198 TEST_ASSERT_EQUAL((int)ActuatorControllerState::NoConnectionAbort,
199 (int)result);
200}
201
208
214
215// ===========================================================================
216// Heartbeat state encoding — verify state→BoardState mapping
217// ===========================================================================
218
220 struct {
222 daq::BoardState expected;
223 } mappings[] = {
236 };
237
238 for (auto& m : mappings) {
240 TEST_ASSERT_EQUAL_MESSAGE(
241 (int)m.expected, (int)got,
242 "State mapping mismatch in getBoardStateForHeartbeat");
243
244 // Also verify: create heartbeat → parse → board_state roundtrips
245 // correctly
246 daq::BoardHeartbeatPacket hb{};
247 hb.board_id = 99;
248 hb.engine_state = daq::EngineState::SAFE;
249 hb.board_state = got;
250
251 uint8_t buf[512];
252 size_t n =
253 daq::create_board_heartbeat_packet(hb, 12345u, buf, sizeof(buf));
254 TEST_ASSERT_GREATER_THAN(0, n);
255
256 daq::PacketHeader hdr_out;
257 daq::BoardHeartbeatPacket hb_out;
258 TEST_ASSERT_TRUE(
259 daq::parse_board_heartbeat_packet(buf, n, hdr_out, hb_out));
260 TEST_ASSERT_EQUAL((int)m.expected, (int)hb_out.board_state);
261 TEST_ASSERT_EQUAL(99, hb_out.board_id);
262 }
263}
264
266 daq::BoardHeartbeatPacket hb{};
267 hb.board_id = 127;
268 hb.engine_state = daq::EngineState::FIRING;
269 hb.board_state =
271
272 uint8_t buf[512];
273 size_t n = daq::create_board_heartbeat_packet(hb, 12346u, buf, sizeof(buf));
274
275 daq::PacketHeader hdr_out;
276 daq::BoardHeartbeatPacket hb_out;
277 TEST_ASSERT_TRUE(
278 daq::parse_board_heartbeat_packet(buf, n, hdr_out, hb_out));
279 TEST_ASSERT_EQUAL(127, hb_out.board_id);
280 TEST_ASSERT_EQUAL((int)daq::EngineState::FIRING, (int)hb_out.engine_state);
281 TEST_ASSERT_EQUAL((int)daq::BoardState::PT_ABORT, (int)hb_out.board_state);
282}
283
284// ===========================================================================
285// Unity runner
286// ===========================================================================
287
288void setUp() {
289}
290void tearDown() {
291}
292
ActuatorControllerState
Definition main.cpp:45
IncomingPacketKind
Definition main.cpp:237
static bool is_abort_controller
Definition main.cpp:63
static ActuatorControllerState state
Definition main.cpp:57
static daq::BoardState getBoardStateForHeartbeat()
Definition main.cpp:167
json_pointer result
Definition json.hpp:14064
bool parse_board_heartbeat_packet(const uint8_t *buffer, size_t buffer_size, PacketHeader &header_out, BoardHeartbeatPacket &data_out)
Parses a Board Heartbeat packet from buffer.
size_t create_board_heartbeat_packet(const BoardHeartbeatPacket &data, uint32_t timestamp_ms, uint8_t *buffer, size_t buffer_size)
Creates a complete Board Heartbeat packet in the provided buffer.
BoardState
Defines the operational state of a board.
Definition DiabloEnums.h:31
*brief user defined string literal for JSON values *sa std::size_t n
Definition json.hpp:24474
int main()
void test_actuator_abort_finished_clear_goes_active()
void test_actuator_active_noconn_abort_stays_active()
void test_actuator_pt_abort_clear_doesnt_transition()
void test_actuator_connloss_heartbeat_goes_active()
void test_actuator_heartbeat_state_mapping_table()
void test_actuator_waiting_config_goes_active()
static ActuatorControllerState applyPacketTransition(ActuatorControllerState state, IncomingPacketKind kind, bool is_abort_controller, bool enable_transitions)
void test_actuator_none_kind_stays()
void test_actuator_active_abort_done_stays_active()
void test_actuator_active_abort_done_goes_abort_finished()
void test_actuator_active_abort_stays_active()
void test_actuator_active_noconn_abort_goes_follower()
void test_actuator_waiting_heartbeat_stays()
void test_actuator_active_abort_goes_abort_finished()
void test_actuator_heartbeat_board_id_preserved()
void test_actuator_noconn_abort_state_clear_doesnt_transition()