test(firmware): event_log boot recovery — partial fill and post-wrap
Exercises the slot-scan logic in event_log_init(): after a simulated reboot (RAM state cleared, NVS slots preserved) the module must resume with the correct head/cnt so newest-first read order is unchanged and subsequent writes continue the seq monotonically. Adds native-only event_log_test_simulate_reboot() helper. Lifts the slot-scan loop out of the #ifdef ARDUINO guard so the native stub exercises the same recovery path as production; the platform-specific NVS setup remains guarded.
This commit is contained in:
@@ -74,6 +74,58 @@ void test_path_hash_distinguishes_real_api_paths() {
|
||||
TEST_ASSERT_NOT_EQUAL(h2, h3);
|
||||
}
|
||||
|
||||
extern "C" void event_log_test_simulate_reboot();
|
||||
|
||||
void test_boot_recovery_after_partial_fill() {
|
||||
// Phase 1: write 5 entries before "reboot"
|
||||
event_log_init();
|
||||
for (uint16_t i = 0; i < 5; i++) event_log_write(EVT_HTTP_OK, i, 0);
|
||||
|
||||
// Phase 2: simulate reboot (clear RAM state, keep slots), re-init, verify
|
||||
event_log_test_simulate_reboot();
|
||||
event_log_init();
|
||||
|
||||
// All 5 original entries should still be readable, newest first
|
||||
EventLogEntry buf[8];
|
||||
size_t n = event_log_read_recent(buf, 8);
|
||||
TEST_ASSERT_EQUAL(5, n);
|
||||
TEST_ASSERT_EQUAL(4, buf[0].data0); // newest
|
||||
TEST_ASSERT_EQUAL(0, buf[4].data0); // oldest
|
||||
|
||||
// Phase 3: write one more — seq must continue (not restart at 0),
|
||||
// so the new entry is the newest and slot index 5 holds it
|
||||
event_log_write(EVT_HTTP_OK, 99, 0);
|
||||
n = event_log_read_recent(buf, 8);
|
||||
TEST_ASSERT_EQUAL(6, n);
|
||||
TEST_ASSERT_EQUAL(99, buf[0].data0);
|
||||
TEST_ASSERT_EQUAL(4, buf[1].data0);
|
||||
}
|
||||
|
||||
void test_boot_recovery_after_wrap() {
|
||||
// Phase 1: write 40 entries (wraps the 32-slot ring once; oldest 8 dropped)
|
||||
event_log_init();
|
||||
for (uint16_t i = 0; i < 40; i++) event_log_write(EVT_HTTP_OK, i, 0);
|
||||
|
||||
// Phase 2: simulate reboot, re-init
|
||||
event_log_test_simulate_reboot();
|
||||
event_log_init();
|
||||
|
||||
// Still 32 entries visible, newest=39, oldest=8
|
||||
EventLogEntry buf[32];
|
||||
size_t n = event_log_read_recent(buf, 32);
|
||||
TEST_ASSERT_EQUAL(32, n);
|
||||
TEST_ASSERT_EQUAL(39, buf[0].data0);
|
||||
TEST_ASSERT_EQUAL(8, buf[31].data0);
|
||||
|
||||
// Phase 3: one more write — newest becomes 100, head advances past
|
||||
// wherever the max-seq slot was, oldest drops to data0=9
|
||||
event_log_write(EVT_HTTP_OK, 100, 0);
|
||||
n = event_log_read_recent(buf, 32);
|
||||
TEST_ASSERT_EQUAL(32, n);
|
||||
TEST_ASSERT_EQUAL(100, buf[0].data0);
|
||||
TEST_ASSERT_EQUAL(9, buf[31].data0);
|
||||
}
|
||||
|
||||
int main() {
|
||||
UNITY_BEGIN();
|
||||
RUN_TEST(test_entry_is_32_bytes);
|
||||
@@ -83,5 +135,7 @@ int main() {
|
||||
RUN_TEST(test_empty_log_read_returns_zero);
|
||||
RUN_TEST(test_read_recent_truncates_to_max_entries);
|
||||
RUN_TEST(test_path_hash_distinguishes_real_api_paths);
|
||||
RUN_TEST(test_boot_recovery_after_partial_fill);
|
||||
RUN_TEST(test_boot_recovery_after_wrap);
|
||||
return UNITY_END();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user