Skip to content

test(comdelay): host unit tests for ComDelay divider/latch tick state machine - #479

Open
Mikefly123 wants to merge 3 commits into
perf/comdelay-divider0-passthroughfrom
test/comdelay-ut
Open

test(comdelay): host unit tests for ComDelay divider/latch tick state machine#479
Mikefly123 wants to merge 3 commits into
perf/comdelay-divider0-passthroughfrom
test/comdelay-ut

Conversation

@Mikefly123

@Mikefly123 Mikefly123 commented Jul 27, 2026

Copy link
Copy Markdown
Contributor

Summary

ComDelay (PROVESFlightControllerReference/Components/ComDelay/) gates radio comStatus by a DIVIDER param, but had zero unit test coverage — the component's CMakeLists.txt UT block was a commented-out template only.

This PR extracts the tick/divider/latch state machine into a header-only, host-testable ComDelayLogic class and adds it to this repo's existing host-side gtest suite (make test-unit), following the same extraction pattern already used for other passive F´ components with ports/params in this repo: RtcHelper (RtcManager), BDot/Magnetorquer/StrategySelector (DetumbleManager), Bypasser (ProvesRouter), and Parser/Validator/Authenticator (TcSecurityDeframer). ComDelay.cpp/.hpp now delegate to ComDelayLogic; no behavior change — verified the extraction preserves the pre-existing atomic compare-exchange consume-once semantics and the 8-bit tick-counter width.

Coverage

  1. Tick-paced release — comStatus latched, released only on a tick where the internal counter is 0.
  2. Divider math — DIVIDER=N releases every N+1 ticks for small N.
  3. Status consumed exactly once — no double-emit of an already-released status.
  4. No release/emit when nothing has been latched.
  5. Runtime divider change mid-cycle (both shrink and grow) doesn't lose or double-emit an already-latched status.
  6. Parameter-invalid fallback to the default divider (and a guard that DIVIDER=0 valid is not mistaken for invalid).

Finding (documented in tests, not fixed here)

DEFAULT_DIVIDER = 299 is commented in ComDelay.fpp as "on a 1Hz tick, transmit every 30S" (i.e. a 300-tick period). In production, however, the tick counter is a U8 (max 255), so it wraps via 8-bit integer overflow at 256 ticks — it never reaches the 299 comparison threshold. The actual default release period is ~256 ticks (~25.6s @ 1Hz), not 300/30s. test_ComDelay_ComDelayLogic.cpp::DefaultDividerActuallyWrapsAt256TicksNot300 pins the real behavior. Flagging this as a pre-existing latent discrepancy worth a follow-up, out of scope for this test-only PR.

Why this matters

Base branch / stacking note

This PR is based directly on feat/usp-radio post-#477 (patch-collapse merged), not stacked on perf/comdelay-divider0-passthrough (#475). #475's branch predates #477 and has drifted (it still carries the pre-collapse individual patches/*.patch files and old west.yml/submodule pins); rebasing it was out of scope for this PR to avoid rewriting another open PR's branch history without explicit sign-off. If #475 is rebased onto current feat/usp-radio first, its DIVIDER=0 passthrough tests (immediate forward without waiting for a tick, no latch set, DIVIDER>0 unchanged) can be layered on top of ComDelayLogic cleanly — the extraction here is what makes that follow-up small.

Test plan

  • make test-unit passes locally: 12/12 tests green, including the 9 new ComDelayLogicTest cases, with no regressions to test_LinkProfiles, test_DetumbleManager_*, test_RtcManager_RtcHelper, test_TcSecurityDeframer_*, test_ProvesRouter_Bypasser.

🤖 Generated with Claude Code


Stack note (2026-07-30): rebased and stacked on #475 (perf/comdelay-divider0-passthrough); base changed accordingly (stack: feat/usp-radio <- #475 <- #479). The rebase ported #475's divider-0 passthrough into the extracted ComDelayLogic (new acceptStatus() — divider 0 forwards immediately without latching; divider > 0 latches as before), and a separate commit adds passthrough test cases (immediate forward w/o latch, 0->N re-latch, N->0 latched-status no-loss/no-double-emit, invalid-param fallback latches) — the coverage closed PR #478 intended. ComDelay suite is now 13 tests; full make test-unit 13/13 suites green.

@coderabbitai

coderabbitai Bot commented Jul 27, 2026

Copy link
Copy Markdown
Contributor

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 0f035efe-4f18-43ef-a3f5-5ac0b6cafa7c

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

Mikefly123 and others added 2 commits July 30, 2026 20:01
ComDelay had no unit test coverage (CMakeLists UT block was a commented
template). Extract the tick/divider/latch state machine into a
host-testable ComDelayLogic class -- following this repo's established
pattern for passive-component logic extraction (RtcHelper, BDot,
Magnetorquer, StrategySelector, Bypasser, Parser/Validator/Authenticator)
-- and add it to the gtest suite driven by `make test-unit`.

ComDelay.cpp/.hpp now delegate to ComDelayLogic; behavior is unchanged
(verified against the pre-existing atomic compare_exchange consume-once
semantics and against the U8 tick-counter width).

Covers: tick-paced release, divider math (small N and the default
divider), exactly-once consumption, no-emit when nothing is latched,
runtime divider changes mid-cycle (shrink and grow), and param-invalid
fallback to the default divider.

Finding: DEFAULT_DIVIDER=299 does not actually yield a ~30s/300-tick
period as commented in ComDelay.fpp -- the production tick counter is a
U8 (max 255), so it wraps via 8-bit overflow at 256 ticks before ever
reaching the 299 comparison threshold. Tests pin the real (256-tick)
behavior rather than the aspirational one; no behavior change made here.
Adds the passthrough test cases that belong with
perf/comdelay-divider0-passthrough (#475), mirroring the coverage
intended by closed PR #478:

- divider-0 forwards immediately (both SUCCESS and FAILURE values)
  without ever setting the latch, so run ticks cannot double-emit
- divider 0 -> N runtime transition latches/tick-paces again
- N -> 0 transition with a status already latched neither loses the
  latched status nor double-emits it (exactly one tick emission)
- invalid DIVIDER parameter falls back to the nonzero default and
  therefore latches, never passthroughs

Kept as a separate commit so the extraction/refactor layer diff of
this branch stays reviewable on its own.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: No status

Development

Successfully merging this pull request may close these issues.

1 participant