mirror of
https://github.com/rstrouse/ESPSomfy-RTS.git
synced 2026-10-31 22:02:17 +01:00
The frame was popped before queueTx(), so whenever the radio queue was busy it was lost. Peek it instead, only remove it once it is queued (or TX is suspended), and don't try while the queue has no room. The repeater buffer moves to TxBuffer.h/.cpp so it can be unit tested. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
114 lines
3.2 KiB
C++
114 lines
3.2 KiB
C++
#include <unity.h>
|
|
#include "TxBuffer.h"
|
|
|
|
void setUp() {}
|
|
void tearDown() {}
|
|
|
|
// Pushes a frame whose payload is all `tag` so frames can be told apart.
|
|
static void pushTagged(somfy_tx_queue_t &q, uint8_t tag, uint8_t bitLength = 56) {
|
|
uint8_t payload[10];
|
|
memset(payload, tag, sizeof(payload));
|
|
q.push(bitLength == 56 ? 2 : 12, payload, bitLength);
|
|
}
|
|
static void assertTagged(const somfy_tx_t &tx, uint8_t tag) {
|
|
uint8_t expected[10];
|
|
memset(expected, tag, sizeof(expected));
|
|
TEST_ASSERT_EQUAL_HEX8_ARRAY(expected, tx.payload, sizeof(expected));
|
|
}
|
|
|
|
static void test_push_then_pop_returns_the_frame() {
|
|
somfy_tx_queue_t q;
|
|
pushTagged(q, 0x11, 80);
|
|
TEST_ASSERT_EQUAL_UINT8(1, q.length);
|
|
somfy_tx_t tx;
|
|
TEST_ASSERT_TRUE(q.pop(&tx));
|
|
TEST_ASSERT_EQUAL_UINT8(12, tx.hwsync);
|
|
TEST_ASSERT_EQUAL_UINT8(80, tx.bit_length);
|
|
assertTagged(tx, 0x11);
|
|
TEST_ASSERT_EQUAL_UINT8(0, q.length);
|
|
}
|
|
static void test_frames_come_out_oldest_first() {
|
|
somfy_tx_queue_t q;
|
|
pushTagged(q, 1);
|
|
pushTagged(q, 2);
|
|
pushTagged(q, 3);
|
|
somfy_tx_t tx;
|
|
for(uint8_t tag = 1; tag <= 3; tag++) {
|
|
TEST_ASSERT_TRUE(q.pop(&tx));
|
|
assertTagged(tx, tag);
|
|
}
|
|
TEST_ASSERT_FALSE(q.pop(&tx));
|
|
}
|
|
static void test_peek_leaves_the_frame_queued() {
|
|
somfy_tx_queue_t q;
|
|
pushTagged(q, 1);
|
|
pushTagged(q, 2);
|
|
somfy_tx_t tx;
|
|
TEST_ASSERT_TRUE(q.peek(&tx));
|
|
assertTagged(tx, 1);
|
|
TEST_ASSERT_TRUE(q.peek(&tx));
|
|
assertTagged(tx, 1);
|
|
TEST_ASSERT_EQUAL_UINT8(2, q.length);
|
|
TEST_ASSERT_TRUE(q.pop(&tx));
|
|
assertTagged(tx, 1);
|
|
TEST_ASSERT_TRUE(q.peek(&tx));
|
|
assertTagged(tx, 2);
|
|
}
|
|
static void test_empty_buffer_has_nothing() {
|
|
somfy_tx_queue_t q;
|
|
somfy_tx_t tx;
|
|
TEST_ASSERT_FALSE(q.peek(&tx));
|
|
TEST_ASSERT_FALSE(q.pop(&tx));
|
|
TEST_ASSERT_EQUAL_UINT8(0, q.length);
|
|
}
|
|
static void test_overflow_drops_the_oldest() {
|
|
somfy_tx_queue_t q;
|
|
for(uint8_t tag = 1; tag <= MAX_TX_BUFFER + 2; tag++) pushTagged(q, tag);
|
|
TEST_ASSERT_EQUAL_UINT8(MAX_TX_BUFFER, q.length);
|
|
somfy_tx_t tx;
|
|
// The first two fell off.
|
|
for(uint8_t tag = 3; tag <= MAX_TX_BUFFER + 2; tag++) {
|
|
TEST_ASSERT_TRUE(q.pop(&tx));
|
|
assertTagged(tx, tag);
|
|
}
|
|
TEST_ASSERT_FALSE(q.pop(&tx));
|
|
}
|
|
static void test_slots_are_reused_after_pop() {
|
|
somfy_tx_queue_t q;
|
|
somfy_tx_t tx;
|
|
// Keep two frames in flight so freed slots are filled again many times over.
|
|
for(uint8_t tag = 1; tag <= 4 * MAX_TX_BUFFER; tag++) {
|
|
pushTagged(q, tag);
|
|
if(tag >= 2) {
|
|
TEST_ASSERT_TRUE(q.pop(&tx));
|
|
assertTagged(tx, tag - 1);
|
|
TEST_ASSERT_EQUAL_UINT8(1, q.length);
|
|
}
|
|
}
|
|
}
|
|
static void test_clear_empties_it() {
|
|
somfy_tx_queue_t q;
|
|
pushTagged(q, 1);
|
|
pushTagged(q, 2);
|
|
q.clear();
|
|
TEST_ASSERT_EQUAL_UINT8(0, q.length);
|
|
somfy_tx_t tx;
|
|
TEST_ASSERT_FALSE(q.peek(&tx));
|
|
pushTagged(q, 3);
|
|
TEST_ASSERT_TRUE(q.pop(&tx));
|
|
assertTagged(tx, 3);
|
|
}
|
|
|
|
int main(int argc, char **argv) {
|
|
(void)argc;
|
|
(void)argv;
|
|
UNITY_BEGIN();
|
|
RUN_TEST(test_push_then_pop_returns_the_frame);
|
|
RUN_TEST(test_frames_come_out_oldest_first);
|
|
RUN_TEST(test_peek_leaves_the_frame_queued);
|
|
RUN_TEST(test_empty_buffer_has_nothing);
|
|
RUN_TEST(test_overflow_drops_the_oldest);
|
|
RUN_TEST(test_slots_are_reused_after_pop);
|
|
RUN_TEST(test_clear_empties_it);
|
|
return UNITY_END();
|
|
}
|