Release packets the interface declines to send (#11087)
This commit is contained in:
co-authored by
GitHub
parent
829ff80a09
commit
290967f739
@@ -15,6 +15,7 @@
|
||||
#include "gps/RTC.h"
|
||||
#include "mesh/NextHopRouter.h"
|
||||
#include "mesh/NodeDB.h"
|
||||
#include "mesh/RadioInterface.h"
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
#include <memory>
|
||||
@@ -87,6 +88,7 @@ class NextHopRouterTestShim : public NextHopRouter
|
||||
using NextHopRouter::noteRouteFailure;
|
||||
using NextHopRouter::noteRouteLearned;
|
||||
using NextHopRouter::noteRouteSuccess;
|
||||
using NextHopRouter::perhapsRebroadcast;
|
||||
using Router::shouldDecrementHopLimit; // protected in Router
|
||||
|
||||
void resetRouteHealthForTest()
|
||||
@@ -96,6 +98,34 @@ class NextHopRouterTestShim : public NextHopRouter
|
||||
}
|
||||
};
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// MockRadioInterface - mirrors RadioLibInterface::send()'s NODENUM_BROADCAST_NO_LORA branch, which
|
||||
// returns ERRNO_SHOULD_RELEASE without releasing.
|
||||
// ---------------------------------------------------------------------------
|
||||
class MockRadioInterface : public RadioInterface
|
||||
{
|
||||
public:
|
||||
ErrorCode send(meshtastic_MeshPacket *p) override
|
||||
{
|
||||
sendCount++;
|
||||
if (declineAll || p->to == NODENUM_BROADCAST_NO_LORA)
|
||||
return ERRNO_SHOULD_RELEASE;
|
||||
|
||||
packetPool.release(p);
|
||||
return ERRNO_OK;
|
||||
}
|
||||
|
||||
uint32_t getPacketTime(uint32_t totalPacketLen, bool received = false) override
|
||||
{
|
||||
(void)totalPacketLen;
|
||||
(void)received;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sendCount = 0;
|
||||
bool declineAll = false;
|
||||
};
|
||||
|
||||
static MockNodeDB *mockNodeDB = nullptr;
|
||||
static NextHopRouterTestShim *shim = nullptr;
|
||||
|
||||
@@ -409,6 +439,65 @@ void test_hoplimit_decrement_when_resolved_not_favorite(void)
|
||||
TEST_ASSERT_TRUE(shim->shouldDecrementHopLimit(&p)); // unique but not a favorite -> decrement
|
||||
}
|
||||
|
||||
// ===========================================================================
|
||||
// Rebroadcast of NODENUM_BROADCAST_NO_LORA
|
||||
// ===========================================================================
|
||||
|
||||
static MockRadioInterface *installMockIface()
|
||||
{
|
||||
MockRadioInterface *m = new MockRadioInterface();
|
||||
shim->addInterface(std::unique_ptr<RadioInterface>(m));
|
||||
return m;
|
||||
}
|
||||
|
||||
// Eligible for rebroadcast: not from/to us, hops left, nonzero id, no next-hop preference.
|
||||
// Encrypted variant so Router::send() skips the encode path.
|
||||
static meshtastic_MeshPacket makeRebroadcastCandidate(NodeNum to)
|
||||
{
|
||||
meshtastic_MeshPacket p = meshtastic_MeshPacket_init_zero;
|
||||
p.from = 0x22222222; // not us
|
||||
p.to = to;
|
||||
p.id = 0x0BADF00D;
|
||||
p.hop_start = 3;
|
||||
p.hop_limit = 3;
|
||||
p.next_hop = NO_NEXT_HOP_PREFERENCE;
|
||||
p.which_payload_variant = meshtastic_MeshPacket_encrypted_tag;
|
||||
p.encrypted.size = 8;
|
||||
return p;
|
||||
}
|
||||
|
||||
// Control: proves the NO_LORA case below turns on the `to` field alone.
|
||||
void test_rebroadcast_normal_broadcast_is_relayed(void)
|
||||
{
|
||||
MockRadioInterface *mockIface = installMockIface();
|
||||
meshtastic_MeshPacket p = makeRebroadcastCandidate(NODENUM_BROADCAST);
|
||||
|
||||
TEST_ASSERT_TRUE_MESSAGE(shim->perhapsRebroadcast(&p), "ordinary broadcast must be rebroadcast");
|
||||
TEST_ASSERT_EQUAL_MESSAGE(1, mockIface->sendCount, "exactly one packet should reach the radio");
|
||||
}
|
||||
|
||||
void test_rebroadcast_no_lora_broadcast_is_not_relayed(void)
|
||||
{
|
||||
MockRadioInterface *mockIface = installMockIface();
|
||||
meshtastic_MeshPacket p = makeRebroadcastCandidate(NODENUM_BROADCAST_NO_LORA);
|
||||
|
||||
TEST_ASSERT_FALSE_MESSAGE(shim->perhapsRebroadcast(&p), "no-LoRa broadcast must not be rebroadcast");
|
||||
TEST_ASSERT_EQUAL_MESSAGE(0, mockIface->sendCount, "no packet should be handed to the radio at all");
|
||||
}
|
||||
|
||||
// Declining mock bypasses the guard so send() is reached; the release itself is only observable as
|
||||
// a sanitizer leak report, not an assertion.
|
||||
void test_rebroadcast_declined_send_releases_packet(void)
|
||||
{
|
||||
MockRadioInterface *mockIface = installMockIface();
|
||||
mockIface->declineAll = true;
|
||||
|
||||
meshtastic_MeshPacket p = makeRebroadcastCandidate(NODENUM_BROADCAST);
|
||||
|
||||
TEST_ASSERT_TRUE_MESSAGE(shim->perhapsRebroadcast(&p), "the rebroadcast must still be attempted");
|
||||
TEST_ASSERT_EQUAL_MESSAGE(1, mockIface->sendCount, "the copy must have reached the mock radio");
|
||||
}
|
||||
|
||||
// ===========================================================================
|
||||
|
||||
void setup()
|
||||
@@ -459,6 +548,11 @@ void setup()
|
||||
RUN_TEST(test_hoplimit_decrement_on_colliding_favorites);
|
||||
RUN_TEST(test_hoplimit_decrement_when_resolved_not_favorite);
|
||||
|
||||
printf("\n=== rebroadcast of NODENUM_BROADCAST_NO_LORA ===\n");
|
||||
RUN_TEST(test_rebroadcast_normal_broadcast_is_relayed);
|
||||
RUN_TEST(test_rebroadcast_no_lora_broadcast_is_not_relayed);
|
||||
RUN_TEST(test_rebroadcast_declined_send_releases_packet);
|
||||
|
||||
exit(UNITY_END());
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user