Fix long name clamping and adjust related structures for compatibility
This commit is contained in:
@@ -1,6 +1,8 @@
|
||||
// Tests for src/mesh/TypeConversions.cpp covering:
|
||||
// - bitfield bit collapse on store + extraction round-trip
|
||||
// - long_name / short_name truncation at the new max_size:25 / 5 boundaries
|
||||
// - long_name / short_name truncation at the storage boundaries (wire User
|
||||
// stays 40 wide for decoding legacy senders; NodeInfoLite stores 25 / 5)
|
||||
// - wire-level decode acceptance of legacy 39-byte long_names
|
||||
// - public_key / hw_model / role pass-through
|
||||
// - thin vs bundled NodeInfo emission
|
||||
//
|
||||
@@ -10,6 +12,8 @@
|
||||
#include "NodeDB.h"
|
||||
#include "TestUtil.h"
|
||||
#include "TypeConversions.h"
|
||||
#include "mesh-pb-constants.h"
|
||||
#include "meshUtils.h"
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
#include <unity.h>
|
||||
@@ -128,6 +132,46 @@ void test_long_name_truncated_utf8_boundary_sanitized(void)
|
||||
TEST_ASSERT_EQUAL_INT('?', lite.long_name[23]);
|
||||
}
|
||||
|
||||
// ---------- wire decode width (decode-liberal, store-narrow) ------------------
|
||||
|
||||
// Hand-built wire-format User payload: field 2 (long_name), wire type 2.
|
||||
static size_t makeUserPayload(uint8_t *buf, size_t nameLen)
|
||||
{
|
||||
size_t i = 0;
|
||||
buf[i++] = 0x12; // tag: field 2, length-delimited
|
||||
buf[i++] = (uint8_t)nameLen;
|
||||
for (size_t j = 0; j < nameLen; j++)
|
||||
buf[i++] = (uint8_t)('A' + (j % 26));
|
||||
return i;
|
||||
}
|
||||
|
||||
void test_wire_decode_accepts_legacy_39_byte_long_name(void)
|
||||
{
|
||||
// The longest name a sender built against the old max_size:40 can emit.
|
||||
// nanopb halts on string overflow rather than truncating, so this only
|
||||
// passes while the wire-facing meshtastic_User stays 40 wide.
|
||||
uint8_t buf[64];
|
||||
size_t len = makeUserPayload(buf, 39);
|
||||
meshtastic_User u = meshtastic_User_init_zero;
|
||||
TEST_ASSERT_TRUE(pb_decode_from_bytes(buf, len, &meshtastic_User_msg, &u));
|
||||
TEST_ASSERT_EQUAL_INT(39, (int)strlen(u.long_name));
|
||||
|
||||
// ...and the store boundary clamps it to the local cap.
|
||||
meshtastic_NodeInfoLite lite = meshtastic_NodeInfoLite_init_default;
|
||||
TypeConversions::CopyUserToNodeInfoLite(&lite, u);
|
||||
TEST_ASSERT_EQUAL_INT(MAX_LONG_NAME_BYTES, (int)strlen(lite.long_name));
|
||||
}
|
||||
|
||||
void test_wire_decode_rejects_name_beyond_wire_limit(void)
|
||||
{
|
||||
// 45 bytes exceeds even the 40-byte wire buffer; the whole message is
|
||||
// rejected (documents the hard outer bound).
|
||||
uint8_t buf[64];
|
||||
size_t len = makeUserPayload(buf, 45);
|
||||
meshtastic_User u = meshtastic_User_init_zero;
|
||||
TEST_ASSERT_FALSE(pb_decode_from_bytes(buf, len, &meshtastic_User_msg, &u));
|
||||
}
|
||||
|
||||
// ---------- short_name truncation --------------------------------------------
|
||||
|
||||
void test_short_name_passes_through(void)
|
||||
@@ -383,6 +427,8 @@ void setup()
|
||||
RUN_TEST(test_long_name_truncates_when_too_long);
|
||||
RUN_TEST(test_long_name_round_trip_to_wire);
|
||||
RUN_TEST(test_long_name_truncated_utf8_boundary_sanitized);
|
||||
RUN_TEST(test_wire_decode_accepts_legacy_39_byte_long_name);
|
||||
RUN_TEST(test_wire_decode_rejects_name_beyond_wire_limit);
|
||||
RUN_TEST(test_short_name_passes_through);
|
||||
RUN_TEST(test_short_name_truncates_when_too_long);
|
||||
RUN_TEST(test_bitfield_is_licensed_round_trip);
|
||||
|
||||
@@ -163,6 +163,47 @@ void test_above_max_codepoint()
|
||||
TEST_ASSERT_TRUE(sanitizeUtf8(buf, sizeof(buf)));
|
||||
}
|
||||
|
||||
// --- clampLongName: local 24-byte cap over wider wire buffers ---
|
||||
|
||||
void test_clamp_long_name_short_unchanged()
|
||||
{
|
||||
char buf[40] = "Kevin Hester";
|
||||
clampLongName(buf);
|
||||
TEST_ASSERT_EQUAL_STRING("Kevin Hester", buf);
|
||||
}
|
||||
|
||||
void test_clamp_long_name_exact_cap_unchanged()
|
||||
{
|
||||
char buf[40] = "abcdefghijklmnopqrstuvwx"; // exactly 24 bytes
|
||||
clampLongName(buf);
|
||||
TEST_ASSERT_EQUAL_STRING("abcdefghijklmnopqrstuvwx", buf);
|
||||
}
|
||||
|
||||
void test_clamp_long_name_truncates_39_bytes()
|
||||
{
|
||||
char buf[40];
|
||||
memset(buf, 'a', 39);
|
||||
buf[39] = '\0';
|
||||
clampLongName(buf);
|
||||
TEST_ASSERT_EQUAL_INT(MAX_LONG_NAME_BYTES, (int)strlen(buf));
|
||||
}
|
||||
|
||||
void test_clamp_long_name_fixes_partial_rune_at_cut()
|
||||
{
|
||||
// 22 ASCII then a 4-byte emoji straddling the 24-byte boundary
|
||||
char buf[40];
|
||||
memset(buf, 'a', 22);
|
||||
buf[22] = '\xF0';
|
||||
buf[23] = '\x9F';
|
||||
buf[24] = '\x8C';
|
||||
buf[25] = '\x99';
|
||||
buf[26] = '\0';
|
||||
clampLongName(buf);
|
||||
TEST_ASSERT_EQUAL_INT(24, (int)strlen(buf));
|
||||
TEST_ASSERT_EQUAL_INT('?', buf[22]);
|
||||
TEST_ASSERT_EQUAL_INT('?', buf[23]);
|
||||
}
|
||||
|
||||
void setup()
|
||||
{
|
||||
UNITY_BEGIN();
|
||||
@@ -191,6 +232,12 @@ void setup()
|
||||
RUN_TEST(test_valid_max_codepoint);
|
||||
RUN_TEST(test_above_max_codepoint);
|
||||
|
||||
// clampLongName
|
||||
RUN_TEST(test_clamp_long_name_short_unchanged);
|
||||
RUN_TEST(test_clamp_long_name_exact_cap_unchanged);
|
||||
RUN_TEST(test_clamp_long_name_truncates_39_bytes);
|
||||
RUN_TEST(test_clamp_long_name_fixes_partial_rune_at_cut);
|
||||
|
||||
exit(UNITY_END());
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user