From 25aebceb2986884d13a179af69af50509ae91f4c Mon Sep 17 00:00:00 2001 From: mikecarper Date: Mon, 5 Oct 2026 19:33:49 -0700 Subject: [PATCH] Verify asynchronous MQTT controls in wireless regressions --- test/test_espnow_radio_lifecycle.py | 16 +++++++++++++++- test/test_mqtt_transport_results.py | 12 ++++++++++-- 2 files changed, 25 insertions(+), 3 deletions(-) diff --git a/test/test_espnow_radio_lifecycle.py b/test/test_espnow_radio_lifecycle.py index c5a8faee6..8626dba85 100644 --- a/test/test_espnow_radio_lifecycle.py +++ b/test/test_espnow_radio_lifecycle.py @@ -121,7 +121,17 @@ class EspNowLifecycleTests(unittest.TestCase): self.assertIn('uint8_t espnow_bridge_enabled = 1;', prefs) self.assertIn('setEspNowBridgeState(enable)', common) self.assertIn('_prefs->espnow_bridge_enabled', common) - self.assertIn('setMqttBridgeState(enable)', common) + mqtt_switch = method(common, 'if (strncmp(config, "mqtt.enabled ", 13) == 0)') + self.assertIn('enable ? _callbacks->setMqttBridgeState(true)', mqtt_switch) + self.assertIn(': _callbacks->requestMqttBridgeStop()', mqtt_switch) + # Reject an unsafe restart before changing saved intent. An accepted + # OFF command saves successfully before signalling cooperative stop. + self.assertLess(mqtt_switch.index('isMqttBridgeStopping()'), + mqtt_switch.index('_prefs->bridge_enabled =')) + self.assertLess(mqtt_switch.index('if (!trySavePrefs())'), + mqtt_switch.index('setMqttBridgeState(true)')) + self.assertLess(mqtt_switch.index('if (!trySavePrefs())'), + mqtt_switch.index('requestMqttBridgeStop()')) self.assertIn('isMqttBridgeRunning()', observer) for role in ('simple_repeater', 'simple_room_server'): header = (ROOT/f'examples/{role}/MyMesh.h').read_text() @@ -129,8 +139,12 @@ class EspNowLifecycleTests(unittest.TestCase): self.assertIn('setMqttBridgeState(true)', combined) self.assertIn('setEspNowBridgeState(true)', combined) mqtt = method(header, 'bool setMqttBridgeState(bool enable) override') + stop = method(header, 'bool requestMqttBridgeStop() override') espnow = method(header, 'bool setEspNowBridgeState(bool enable) override') self.assertIn('if (espnow_bridge.isRunning()) espnow_bridge.end();', mqtt) + self.assertLess(mqtt.index('isStopping()'), mqtt.index('espnow_bridge.end()')) + self.assertIn('->requestStop()', stop) + self.assertNotIn('->end()', stop) self.assertIn('if (mqtt_bridge' if role == 'simple_repeater' else 'if (bridge', espnow) def test_sdk_failures_stop_and_restart(self): diff --git a/test/test_mqtt_transport_results.py b/test/test_mqtt_transport_results.py index 000eb538b..b445ca3d1 100644 --- a/test/test_mqtt_transport_results.py +++ b/test/test_mqtt_transport_results.py @@ -155,9 +155,17 @@ int main() { reconnect_result=ESP_OK; assert(b.reconnectSlotClient(0)==ESP_OK && b._slot_attempt_pending[0]); const int stopped_starts = start_calls, stopped_reconnects = reconnect_calls; + const auto stopped_failures = b._slots[0].start_failures; b._stop_requested = true; - assert(b.reconnectSlotClient(0)==ESP_ERR_INVALID_STATE); - assert(start_calls==stopped_starts && reconnect_calls==stopped_reconnects); + assert(b.reconnectSlotClient(-1)==ESP_ERR_INVALID_ARG); + for (bool started : {false, true}) { + c._started = started; + b._slot_attempt_pending[0] = started; + assert(b.reconnectSlotClient(0)==ESP_ERR_INVALID_STATE); + assert(start_calls==stopped_starts && reconnect_calls==stopped_reconnects); + assert(b._slot_attempt_pending[0]==started && b._slots[0].start_failures==stopped_failures); + } + b._stop_requested = false; return 0; } '''