mirror of https://github.com/meshcore-dev/MeshCore
Browse Source
hasSeen() was simultaneously a predicate and a mutator — it inserted the packet hash on every miss, making five call sites that only wanted to mark a packet as sent call it with the return value discarded. Split into: - wasSeen() — pure predicate, no side effects - markSeen() — explicit insert All query sites now call markSeen() immediately after wasSeen() returns false, preserving identical runtime behaviour. The five mark-only send sites (sendFlood, sendDirect, sendZeroHop x2) now call markSeen directly. Also fixes three bridge sites (BridgeBase, ESPNowBridge, RS232Bridge) that had the same query+implicit-insert pattern. Tests: add test/test_mesh_tables/ covering wasSeen purity, markSeen, dup stats, and clear. Update SHA256 mock to produce deterministic output (previously finalize() was a no-op). Add Packet.cpp to native build filter.pull/2880/head
10 changed files with 176 additions and 32 deletions
@ -0,0 +1,103 @@ |
|||||
|
#include <gtest/gtest.h> |
||||
|
#include "helpers/SimpleMeshTables.h" |
||||
|
|
||||
|
using namespace mesh; |
||||
|
|
||||
|
// Build a packet that calculatePacketHash() distinguishes by payload content.
|
||||
|
// header selects ROUTE_TYPE_FLOOD so isRouteDirect() returns false.
|
||||
|
static Packet makeFloodPacket(uint8_t seed) { |
||||
|
Packet p; |
||||
|
p.header = ROUTE_TYPE_FLOOD | (PAYLOAD_TYPE_ACK << PH_TYPE_SHIFT); |
||||
|
p.payload[0] = seed; |
||||
|
p.payload_len = 1; |
||||
|
p.path_len = 0; |
||||
|
return p; |
||||
|
} |
||||
|
|
||||
|
static Packet makeDirectPacket(uint8_t seed) { |
||||
|
Packet p; |
||||
|
p.header = ROUTE_TYPE_DIRECT | (PAYLOAD_TYPE_ACK << PH_TYPE_SHIFT); |
||||
|
p.payload[0] = seed; |
||||
|
p.payload_len = 1; |
||||
|
p.path_len = 0; |
||||
|
return p; |
||||
|
} |
||||
|
|
||||
|
// ── wasSeen: pure query ───────────────────────────────────────────────────────
|
||||
|
|
||||
|
TEST(SimpleMeshTables, WasSeen_ReturnsFalseForUnseen) { |
||||
|
SimpleMeshTables t; |
||||
|
Packet p = makeFloodPacket(0x01); |
||||
|
EXPECT_FALSE(t.wasSeen(&p)); |
||||
|
} |
||||
|
|
||||
|
// wasSeen shouldn't change state
|
||||
|
TEST(SimpleMeshTables, WasSeen_IsPureQuery_DoesNotInsert) { |
||||
|
SimpleMeshTables t; |
||||
|
Packet p = makeFloodPacket(0x01); |
||||
|
EXPECT_FALSE(t.wasSeen(&p)); |
||||
|
EXPECT_FALSE(t.wasSeen(&p)); |
||||
|
} |
||||
|
|
||||
|
// ── markSeen + wasSeen ───────────────────────────────────────────────────────
|
||||
|
|
||||
|
TEST(SimpleMeshTables, MarkSeen_MakesWasSeenReturnTrue) { |
||||
|
SimpleMeshTables t; |
||||
|
Packet p = makeFloodPacket(0x01); |
||||
|
t.markSeen(&p); |
||||
|
EXPECT_TRUE(t.wasSeen(&p)); |
||||
|
} |
||||
|
|
||||
|
TEST(SimpleMeshTables, MarkSeen_DoesNotAffectOtherPackets) { |
||||
|
SimpleMeshTables t; |
||||
|
Packet p1 = makeFloodPacket(0x01); |
||||
|
Packet p2 = makeFloodPacket(0x02); |
||||
|
t.markSeen(&p1); |
||||
|
EXPECT_FALSE(t.wasSeen(&p2)); |
||||
|
} |
||||
|
|
||||
|
// Canonical pattern used at every onRecvPacket call site:
|
||||
|
// if (!wasSeen(pkt)) { markSeen(pkt); process(pkt); }
|
||||
|
TEST(SimpleMeshTables, QueryThenMark_WorksCorrectly) { |
||||
|
SimpleMeshTables t; |
||||
|
Packet p = makeFloodPacket(0x01); |
||||
|
EXPECT_FALSE(t.wasSeen(&p)); |
||||
|
t.markSeen(&p); |
||||
|
EXPECT_TRUE(t.wasSeen(&p)); |
||||
|
} |
||||
|
|
||||
|
// ── dup stats ────────────────────────────────────────────────────────────────
|
||||
|
|
||||
|
TEST(SimpleMeshTables, WasSeen_IncrementsFloodDupStat) { |
||||
|
SimpleMeshTables t; |
||||
|
Packet p = makeFloodPacket(0x01); |
||||
|
t.markSeen(&p); |
||||
|
t.wasSeen(&p); |
||||
|
EXPECT_EQ(1u, t.getNumFloodDups()); |
||||
|
EXPECT_EQ(0u, t.getNumDirectDups()); |
||||
|
} |
||||
|
|
||||
|
TEST(SimpleMeshTables, WasSeen_IncrementsDirectDupStat) { |
||||
|
SimpleMeshTables t; |
||||
|
Packet p = makeDirectPacket(0x01); |
||||
|
t.markSeen(&p); |
||||
|
t.wasSeen(&p); |
||||
|
EXPECT_EQ(0u, t.getNumFloodDups()); |
||||
|
EXPECT_EQ(1u, t.getNumDirectDups()); |
||||
|
} |
||||
|
|
||||
|
// ── clear ────────────────────────────────────────────────────────────────────
|
||||
|
|
||||
|
TEST(SimpleMeshTables, Clear_RemovesSeenPacket) { |
||||
|
SimpleMeshTables t; |
||||
|
Packet p = makeFloodPacket(0x01); |
||||
|
t.markSeen(&p); |
||||
|
ASSERT_TRUE(t.wasSeen(&p)); |
||||
|
t.clear(&p); |
||||
|
EXPECT_FALSE(t.wasSeen(&p)); |
||||
|
} |
||||
|
|
||||
|
int main(int argc, char** argv) { |
||||
|
::testing::InitGoogleTest(&argc, argv); |
||||
|
return RUN_ALL_TESTS(); |
||||
|
} |
||||
Loading…
Reference in new issue