From e247f70c6dc48bd328969e5542b1e3de9da34b36 Mon Sep 17 00:00:00 2001 From: Ben Meadors Date: Tue, 21 Jul 2026 05:27:23 -0500 Subject: [PATCH] test: drain toPhoneQueue in MQTT test to fix ASan leak sendLocal() now dispatches local packets through handleReceived() directly instead of the mock-overridden enqueueReceivedMessage(). The MQTT implicit ACK-to-self therefore runs the full receive pipeline (RoutingModule -> MeshService::handleFromRadio -> sendToPhone), enqueuing pooled MeshPacket copies into toPhoneQueue. Production drains that queue via PhoneAPI, but the test has no phone reader, so the copies leaked at teardown (LeakSanitizer: 42824 bytes / 101 objects across test_receiveFuzzServiceEnvelope and test_receiveAcksOwnSentMessages). Give MockMeshService a destructor that drains toPhoneQueue like the phone would. Test-only; the real firmware does not leak here. --- test/test_mqtt/MQTT.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/test/test_mqtt/MQTT.cpp b/test/test_mqtt/MQTT.cpp index 270e8abe3..78f8b32f5 100644 --- a/test/test_mqtt/MQTT.cpp +++ b/test/test_mqtt/MQTT.cpp @@ -53,6 +53,15 @@ class MockRouter : public Router class MockMeshService : public MeshService { public: + // No PhoneAPI reader exists in these tests, so packets the receive pipeline forwards to the phone + // (MeshService::sendToPhone enqueues pooled copies into toPhoneQueue) would leak at teardown. Drain + // the queue like the phone would. This surfaced once sendLocal() began dispatching local packets + // through handleReceived() directly rather than via the (mock-overridden) enqueueReceivedMessage(). + ~MockMeshService() + { + while (meshtastic_MeshPacket *p = getForPhone()) + releaseToPool(p); + } void sendMqttMessageToClientProxy(meshtastic_MqttClientProxyMessage *m) override { messages_.emplace_back(*m);