test(firmware): broaden native-test coverage + gcov instrumentation
Extract the pre-first-image retry from normal_operation() into a templated bootstrap_loop() helper in operation.h so the loop body becomes unit-testable. Add four tests against it: two that verify the X-Panel-Id header is sent on every poll and matches the compile-time PANEL_ID (a silent server-side mis-routing risk if dropped), and two that exercise the loop's exit-on-deep-sleep vs. iterate-while-204 behaviour. Wire --coverage into env:native-test (compile + link via a post-script) so `gcovr -r . --filter src/` produces a real number, and ignore the stray *.gcov files gcovr drops at the repo root. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
+4
-4
@@ -292,13 +292,13 @@ static void normal_operation(const String& mac) {
|
||||
// we've received our first image. While in the pre-image window it
|
||||
// returns instead, so we keep WiFi up and retry on a short interval —
|
||||
// way faster end-to-end than waiting through a deep-sleep + reconnect
|
||||
// for every "no image yet" poll.
|
||||
while (true) {
|
||||
// for every "no image yet" poll. The loop body is extracted into
|
||||
// bootstrap_loop() (operation.h) so it's unit-testable.
|
||||
bootstrap_loop([&]() {
|
||||
HTTPClient http;
|
||||
http.begin(client, url);
|
||||
normal_operation_impl(mac, http, url, prefs);
|
||||
delay(BOOTSTRAP_RETRY_INTERVAL_MS);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// ── Setup ─────────────────────────────────────────────────────────────────────
|
||||
|
||||
@@ -356,3 +356,23 @@ void normal_operation_impl(const String& mac, HTTP& http, const String& url, Pre
|
||||
esp_sleep_enable_ext0_wakeup((gpio_num_t)PIN_BTN_RESET, 0);
|
||||
esp_deep_sleep_start();
|
||||
}
|
||||
|
||||
// ── Bootstrap-stay-awake loop ────────────────────────────────────────────────
|
||||
// Wraps normal_operation_impl in a retry loop for the pre-first-image window.
|
||||
// Once an image arrives, impl calls esp_deep_sleep_start() and never returns —
|
||||
// in production that's literal silicon-level halt; in unit tests the mock just
|
||||
// sets g_deep_sleep_started and returns, so we check that flag to break out.
|
||||
// Caller passes a callable that runs one poll iteration (instantiates a fresh
|
||||
// HTTPClient bound to the WiFiClient, calls normal_operation_impl, etc.).
|
||||
template<typename PollOnce>
|
||||
inline void bootstrap_loop(PollOnce poll_once) {
|
||||
while (true) {
|
||||
poll_once();
|
||||
#ifdef UNIT_TEST
|
||||
// Production: esp_deep_sleep_start never returns. Tests: it sets the
|
||||
// flag and returns, so without this guard the loop spins forever.
|
||||
if (g_deep_sleep_started) return;
|
||||
#endif
|
||||
delay(BOOTSTRAP_RETRY_INTERVAL_MS);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user