Fix OTA retry accounting and radio delivery races

Keep catalog, manifest and leaf requests pending when the local transmit
queue rejects them instead of spending their network retry allowance.

Keep the packet selected before CAD so work becoming due during sensing
cannot bypass its own channel or pacing checks. Retire cancelled radio
retries before waiting for BUSY hardware or their retry deadline.

Wait for active transmission completion before applying firmware. Stop
admitting new transmissions after the apply drain deadline so busy queues
cannot postpone reboot indefinitely, and keep those deadlines armed across
millis rollover. Retain the existing persistence-flush backoff.

Add failing-before/fixed-after regression coverage for all four issues,
including the production OTA apply and TX guards in CI.

Validation: 1,496 native tests, 42 Python integration tests, and five
firmware builds passed across ESP32-S3, nRF52, and STM32 targets.
This commit is contained in:
mikecarper committed 2026-09-15 06:45:28 -07:00
1 parent b2f2b5bf02
commit 5d69aa461f
11 files changed
+312 -24

No files matched your search

+6
View File
@@ -177,6 +177,12 @@ does not reflect the GoogleTest count -- run the built binary directly
`test_trace_retry` checks both profile copies, stable dual-profile airtime, and
ordinary traffic during OTA pacing; `test_packet_manager` checks that intentional
pacing survives stale expiry without erasing prior congestion age.
- OTA delivery: `test_ota` keeps rejected queue admissions out of metadata retry
limits; `test_trace_retry` advances the clock during CAD to catch selection and
pacing bypasses and cancels retries while the chip stays BUSY.
`python3 -B test/test_ota_apply_delivery.py -v` executes the
production apply/TX guards with a reply on air, a busy queue, failed persistence,
and clock rollover. It checks application and bootloader reboot paths.
- To add a suite: create `test/test_<name>/test_<name>.cpp` with a `main()`, and
add any host-only source it links to the `native` env's `build_src_filter` in
`platformio.ini` (header-only code needs no source entry). No other wiring.