Files
HaloKeymind/test/test_companion_frame_queue/test_companion_frame_queue.cpp
mikecarper ecaa5ac2a0 Harden nRF52 OTA, USB sessions, and T096 controls
Bind Companion replies to request transports, make dual-CDC USB sessions nonblocking and reconnect-safe, and harden nRF52 watchdog/OTA storage paths. Fix T096 button debounce, display wake, sleep races, and the compact message layout; add exact WisBlock OTA profiles plus expanded native/static/HIL documentation.
2026-09-01 20:51:43 -07:00

180 lines
5.9 KiB
C++

#include <gtest/gtest.h>
#include <helpers/CompanionFrameQueue.h>
#include <helpers/CompanionHardwareCommandCompat.h>
namespace {
struct TestFrame {
size_t len;
uint8_t buf[8];
};
static bool enqueue(TestFrame queue[], size_t& count, size_t capacity,
uint8_t code) {
return mesh::enqueueCompanionFrame(queue, count, capacity, &code, 1);
}
TEST(CompanionFrameQueue, HighBitSeparatesResponsesFromPushes) {
const uint8_t highest_command_or_response = 0x7F;
const uint8_t first_push = 0x80;
const uint8_t unknown_high_code = 0x98;
EXPECT_FALSE(mesh::isCompanionPushFrame(&highest_command_or_response, 1));
EXPECT_TRUE(mesh::isCompanionPushFrame(&first_push, 1));
EXPECT_TRUE(mesh::isCompanionPushFrame(&unknown_high_code, 1));
}
TEST(CompanionFrameQueue, PushTrafficLeavesOneResponseSlot) {
TestFrame queue[4] = {};
size_t count = 0;
EXPECT_TRUE(enqueue(queue, count, 4, 0x88));
EXPECT_TRUE(enqueue(queue, count, 4, 0x84));
EXPECT_TRUE(enqueue(queue, count, 4, 0x81));
EXPECT_FALSE(enqueue(queue, count, 4, 0x8A));
ASSERT_EQ(3U, count);
EXPECT_TRUE(enqueue(queue, count, 4, 0x00));
ASSERT_EQ(4U, count);
EXPECT_EQ(0x00, queue[0].buf[0]);
}
TEST(CompanionFrameQueue, RequiredPushEvictsBestEffortTraffic) {
TestFrame queue[4] = {
{1, {0x06}}, {1, {0x82}}, {1, {0x88}}, {1, {0x84}}};
size_t count = 4;
ASSERT_TRUE(enqueue(queue, count, 4, 0x8B));
ASSERT_EQ(4U, count);
EXPECT_EQ(0x06, queue[0].buf[0]);
EXPECT_EQ(0x82, queue[1].buf[0]);
EXPECT_EQ(0x8B, queue[2].buf[0]);
EXPECT_EQ(0x88, queue[3].buf[0]);
}
TEST(CompanionFrameQueue, RequiredPushesRemainFifoAheadOfLogs) {
TestFrame queue[6] = {};
size_t count = 0;
ASSERT_TRUE(enqueue(queue, count, 6, 0x88));
ASSERT_TRUE(enqueue(queue, count, 6, 0x82));
ASSERT_TRUE(enqueue(queue, count, 6, 0x84));
ASSERT_TRUE(enqueue(queue, count, 6, 0x85));
ASSERT_EQ(4U, count);
EXPECT_EQ(0x82, queue[0].buf[0]);
EXPECT_EQ(0x85, queue[1].buf[0]);
EXPECT_EQ(0x88, queue[2].buf[0]);
EXPECT_EQ(0x84, queue[3].buf[0]);
}
TEST(CompanionFrameQueue, MessageWaitingCoalesces) {
TestFrame queue[4] = {};
size_t count = 0;
ASSERT_TRUE(enqueue(queue, count, 4, 0x83));
ASSERT_TRUE(enqueue(queue, count, 4, 0x83));
EXPECT_EQ(1U, count);
}
TEST(CompanionFrameQueue, UnknownPushDefaultsToRequired) {
uint8_t unknown = 0xF1;
EXPECT_TRUE(mesh::companionFrameRequiresDelivery(&unknown, 1));
uint8_t packet_log = 0x88;
EXPECT_FALSE(mesh::companionFrameRequiresDelivery(&packet_log, 1));
}
TEST(CompanionFrameQueue, QueuePriorityDoesNotImplyRequesterOwnership) {
uint8_t response = 0x05;
uint8_t login_result = 0x85;
uint8_t message_waiting = 0x83;
uint8_t control_data = 0x8E;
uint8_t unknown = 0xF1;
EXPECT_TRUE(mesh::companionFrameUsesRequesterRoute(&response, 1));
EXPECT_TRUE(mesh::companionFrameUsesRequesterRoute(&login_result, 1));
EXPECT_FALSE(mesh::companionFrameUsesRequesterRoute(&message_waiting, 1));
EXPECT_FALSE(mesh::companionFrameUsesRequesterRoute(&control_data, 1));
EXPECT_FALSE(mesh::companionFrameUsesRequesterRoute(&unknown, 1));
EXPECT_TRUE(mesh::companionFrameRequiresDelivery(&message_waiting, 1));
EXPECT_TRUE(mesh::companionFrameRequiresDelivery(&control_data, 1));
}
TEST(CompanionFrameQueue, ResponsesRunBeforeQueuedPushesAndRemainFifo) {
TestFrame queue[5] = {};
size_t count = 0;
ASSERT_TRUE(enqueue(queue, count, 5, 0x88));
ASSERT_TRUE(enqueue(queue, count, 5, 0x06));
ASSERT_TRUE(enqueue(queue, count, 5, 0x84));
ASSERT_TRUE(enqueue(queue, count, 5, 0x00));
ASSERT_EQ(4U, count);
EXPECT_EQ(0x06, queue[0].buf[0]);
EXPECT_EQ(0x00, queue[1].buf[0]);
EXPECT_EQ(0x88, queue[2].buf[0]);
EXPECT_EQ(0x84, queue[3].buf[0]);
}
TEST(CompanionFrameQueue, ResponseEvictsNewestPushFromAnAlreadyFullQueue) {
TestFrame queue[4] = {
{1, {0x06}}, {1, {0x88}}, {1, {0x00}}, {1, {0x84}}};
size_t count = 4;
ASSERT_TRUE(enqueue(queue, count, 4, 0x01));
ASSERT_EQ(4U, count);
EXPECT_EQ(0x06, queue[0].buf[0]);
EXPECT_EQ(0x00, queue[1].buf[0]);
EXPECT_EQ(0x01, queue[2].buf[0]);
EXPECT_EQ(0x88, queue[3].buf[0]);
}
TEST(CompanionFrameQueue, ResponseDoesNotEvictAnotherResponse) {
TestFrame queue[3] = {
{1, {0x00}}, {1, {0x01}}, {1, {0x06}}};
size_t count = 3;
EXPECT_FALSE(enqueue(queue, count, 3, 0x02));
EXPECT_EQ(3U, count);
EXPECT_EQ(0x00, queue[0].buf[0]);
EXPECT_EQ(0x01, queue[1].buf[0]);
EXPECT_EQ(0x06, queue[2].buf[0]);
}
TEST(CompanionHardwareCommandCompat, Command66TextWinsOverBareLegacyGet) {
EXPECT_FALSE(mesh::companion::isRunCliFrame(0x42, 1));
EXPECT_TRUE(mesh::companion::isFemRxGainGet(0x42));
EXPECT_TRUE(mesh::companion::isRunCliFrame(0x42, 2));
EXPECT_FALSE(mesh::companion::isRunCliFrame(0x41, 2));
}
TEST(CompanionHardwareCommandCompat, BothShippedAliasBlocksRemainInbound) {
EXPECT_TRUE(mesh::companion::isFemRxGainGet(0x42));
EXPECT_TRUE(mesh::companion::isFemRxGainGet(0x78));
EXPECT_TRUE(mesh::companion::isFemRxGainSet(0x43));
EXPECT_TRUE(mesh::companion::isFemRxGainSet(0x79));
EXPECT_TRUE(mesh::companion::isRadioRxGainGet(0x44));
EXPECT_TRUE(mesh::companion::isRadioRxGainGet(0x7A));
EXPECT_TRUE(mesh::companion::isRadioRxGainSet(0x45));
EXPECT_TRUE(mesh::companion::isRadioRxGainSet(0x7B));
EXPECT_TRUE(mesh::companion::isWiFiPowerSaveGet(0x46));
EXPECT_TRUE(mesh::companion::isWiFiPowerSaveGet(0x7C));
EXPECT_TRUE(mesh::companion::isWiFiPowerSaveSet(0x47));
EXPECT_TRUE(mesh::companion::isWiFiPowerSaveSet(0x7D));
EXPECT_TRUE(mesh::companion::isBluetoothNameGet(0x48));
EXPECT_TRUE(mesh::companion::isBluetoothNameGet(0x7E));
EXPECT_TRUE(mesh::companion::isBluetoothNameSet(0x49));
EXPECT_TRUE(mesh::companion::isBluetoothNameSet(0x7F));
EXPECT_FALSE(mesh::companion::isRadioRxGainGet(0x78));
EXPECT_FALSE(mesh::companion::isWiFiPowerSaveSet(0x7F));
}
} // namespace
int main(int argc, char** argv) {
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}