Skip to content

Commit 4ef76a7

Browse files
authored
Merge pull request ExpressLRS#3331 from valeriyvan/fifo-skip
Fix bug in FIFO skip() leading to internal state corruption, add tests
2 parents 134d69a + b3fc4a0 commit 4ef76a7

File tree

2 files changed

+109
-2
lines changed

2 files changed

+109
-2
lines changed

src/lib/FIFO/FIFO.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -335,7 +335,8 @@ class FIFO
335335
*/
336336
ICACHE_RAM_ATTR void skip(const uint16_t len)
337337
{
338-
numElements -= std::min((uint32_t)len, numElements);
339-
head = (head + len) % FIFO_SIZE;
338+
uint32_t skipCount = std::min((uint32_t)len, numElements);
339+
numElements -= skipCount;
340+
head = (head + skipCount) % FIFO_SIZE;
340341
}
341342
};

src/test/test_fifo/test_fifo.cpp

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,107 @@ void test_fifo_ensure()
5858
TEST_ASSERT_EQUAL(10, f.pop()); // and that all the bytes in the head packet are what we expect
5959
}
6060

61+
void test_fifo_skip_basic()
62+
{
63+
f.flush();
64+
65+
// Add 5 elements
66+
for(int i = 0; i < 5; i++) {
67+
f.push(i + 10);
68+
}
69+
TEST_ASSERT_EQUAL(5, f.size());
70+
71+
// Skip 3 elements
72+
f.skip(3);
73+
TEST_ASSERT_EQUAL(2, f.size());
74+
75+
// Remaining elements should be correct
76+
TEST_ASSERT_EQUAL(13, f.pop());
77+
TEST_ASSERT_EQUAL(14, f.pop());
78+
TEST_ASSERT_EQUAL(0, f.size());
79+
}
80+
81+
void test_fifo_skip_overflow()
82+
{
83+
f.flush();
84+
85+
// Add 5 elements
86+
for(int i = 0; i < 5; i++) {
87+
f.push(i + 10);
88+
}
89+
TEST_ASSERT_EQUAL(5, f.size());
90+
91+
// Try to skip 20 elements (but only 5 exist)
92+
// This should skip all 5 and leave FIFO empty
93+
f.skip(20);
94+
TEST_ASSERT_EQUAL(0, f.size());
95+
96+
// FIFO should be in consistent state - can add new elements
97+
f.push(99);
98+
TEST_ASSERT_EQUAL(1, f.size());
99+
TEST_ASSERT_EQUAL(99, f.pop());
100+
TEST_ASSERT_EQUAL(0, f.size());
101+
}
102+
103+
void test_fifo_skip_wraparound()
104+
{
105+
f.flush();
106+
107+
// Fill buffer near capacity and advance head by popping
108+
for(int i = 0; i < 200; i++) {
109+
f.push(i);
110+
f.pop(); // Advance head to near end of buffer
111+
}
112+
113+
// Add elements that will wrap around
114+
f.push(100);
115+
f.push(101);
116+
f.push(102);
117+
TEST_ASSERT_EQUAL(3, f.size());
118+
119+
// Skip more elements than exist with wrap-around
120+
f.skip(10);
121+
TEST_ASSERT_EQUAL(0, f.size());
122+
123+
// Should be able to add elements normally
124+
f.push(200);
125+
f.push(201);
126+
TEST_ASSERT_EQUAL(2, f.size());
127+
TEST_ASSERT_EQUAL(200, f.pop());
128+
TEST_ASSERT_EQUAL(201, f.pop());
129+
}
130+
131+
void test_fifo_skip_zero()
132+
{
133+
f.flush();
134+
135+
// Add elements
136+
f.push(10);
137+
f.push(11);
138+
TEST_ASSERT_EQUAL(2, f.size());
139+
140+
// Skip zero elements should not change anything
141+
f.skip(0);
142+
TEST_ASSERT_EQUAL(2, f.size());
143+
TEST_ASSERT_EQUAL(10, f.pop());
144+
TEST_ASSERT_EQUAL(11, f.pop());
145+
}
146+
147+
void test_fifo_skip_empty()
148+
{
149+
f.flush();
150+
TEST_ASSERT_EQUAL(0, f.size());
151+
152+
// Skip on empty FIFO should do nothing
153+
f.skip(10);
154+
TEST_ASSERT_EQUAL(0, f.size());
155+
156+
// Should still be able to add elements
157+
f.push(42);
158+
TEST_ASSERT_EQUAL(1, f.size());
159+
TEST_ASSERT_EQUAL(42, f.pop());
160+
}
161+
61162
// Unity setup/teardown
62163
void setUp() {}
63164
void tearDown() {}
@@ -68,6 +169,11 @@ int main(int argc, char **argv)
68169
RUN_TEST(test_fifo_pop_wrap);
69170
RUN_TEST(test_fifo_popBytes_wrap);
70171
RUN_TEST(test_fifo_ensure);
172+
RUN_TEST(test_fifo_skip_basic);
173+
RUN_TEST(test_fifo_skip_overflow);
174+
RUN_TEST(test_fifo_skip_wraparound);
175+
RUN_TEST(test_fifo_skip_zero);
176+
RUN_TEST(test_fifo_skip_empty);
71177
UNITY_END();
72178

73179
return 0;

0 commit comments

Comments
 (0)