Skip to content

Make the Kotlin v18-aux prune threshold injectable, as Swift's already is (#888) - #904

Merged
ryanbr merged 1 commit into
mainfrom
fix/kotlin-v18aux-prune-test-parity
Jul 27, 2026
Merged

Make the Kotlin v18-aux prune threshold injectable, as Swift's already is (#888)#904
ryanbr merged 1 commit into
mainfrom
fix/kotlin-v18aux-prune-test-parity

Conversation

@ryanbr

@ryanbr ryanbr commented Jul 27, 2026

Copy link
Copy Markdown
Owner

DeepCaptureMigrationTest.repositoryInsertV18Aux_insertsThenPrunes has been failing on main since #888. Found by @vishk23 while running the suite for #896, and correctly identified there as pre-existing rather than theirs.

What broke

#888 made the v18-aux sweep amortised — WhoopRepository prunes once per V18_AUX_PRUNE_EVERY_ROWS (10 000) rows instead of on every batch. The test inserts one row and asserts pruneV18Aux fired, which the amortised path cannot do.

The Swift half of #888 handled exactly this: StreamStore.insert takes v18AuxRetentionRows and v18AuxPruneEveryRows as parameters, and DeepCaptureChannelsTests passes 1, 7 and 5_000 to exercise the sweep, the deferral and the counter reset. The Kotlin twin kept reading the companion constants, so no test could observe a sweep without inserting ten thousand rows — and the one test that tried was left asserting pre-#888 behaviour.

android.yml is disabled, so nothing reported it. That is the cost of the gap, made concrete.

The fix

WhoopRepository.insert takes both as defaulted parameters, mirroring the Swift signature. Production callers pass neither and get the shipped constants. Every existing call site passes exactly two arguments, so appending defaulted parameters leaves them binding as before — checked, not assumed.

The alternative was loosening the assertion to accept no sweep, which would have deleted the only Kotlin coverage of the retention path rather than fixing it.

Coverage brought up to Swift's

The fixed test now says why it needs a threshold of 1. Two more pin the amortisation itself:

  • three rows against a 5 000-row budget sweep nothing (testRetentionSweepIsDeferredBelowTheThreshold)
  • two rows per batch against a budget of 3 sweep exactly once, because the counter resets (testRetentionSweepRunsOnceTheThresholdIsCrossed + testTheAmortisationCounterResetsAfterEachSweep)

Verification

  • The three expected sweep counts were re-derived by simulating the exact gate — banked accumulates per device, sweeps at >= budget, resets only on a successful sweep — rather than by arithmetic in my head. All three match.
  • All .insert( call sites checked for positional-argument binding.
  • doc_comment_lint passes.

Not compiled. Gradle cannot run on this host (aapt2 is x86-64 only) and no CI job builds Android. Worth a local ./gradlew testFullDebugUnitTest before merge — and this PR is itself the argument for enabling android.yml, since a disabled job is why a red test sat on main unnoticed.

…y is (#888)

`DeepCaptureMigrationTest.repositoryInsertV18Aux_insertsThenPrunes` has been
failing on main since #888. It inserts one aux row and asserts pruneV18Aux
fired, which the amortised sweep cannot do — that PR changed the sweep to run
once per V18_AUX_PRUNE_EVERY_ROWS (10 000) rows rather than on every batch.

The Swift half of #888 handled this: StreamStore.insert takes
v18AuxRetentionRows and v18AuxPruneEveryRows as parameters, and
DeepCaptureChannelsTests passes 1, 7 and 5 000 to exercise the sweep, the
deferral and the counter reset. The Kotlin twin kept reading the companion
constants, so no test could observe the sweep without inserting ten thousand
rows, and the one test that tried was left asserting the pre-#888 behaviour.
android.yml is disabled, so nothing reported it. Found by @vishk23 while running
the suite for #896, and correctly identified there as pre-existing rather than
theirs.

WhoopRepository.insert now takes both as defaulted parameters, mirroring the
Swift signature. Production callers pass neither and get the shipped constants;
every existing call site passes exactly two arguments, so appending defaulted
parameters leaves them binding as before.

Also brings the Kotlin coverage up to what Swift has had since #888: the fixed
test now states why it needs a threshold of 1, and two more pin the amortisation
itself — that three rows against a 5 000-row budget sweep nothing, and that two
rows per batch against a budget of 3 sweep exactly once because the counter
resets. Those are the twins of testRetentionSweepIsDeferredBelowTheThreshold,
testRetentionSweepRunsOnceTheThresholdIsCrossed and
testTheAmortisationCounterResetsAfterEachSweep.

Verified: the three expected sweep counts were re-derived by simulating the exact
gate (banked accumulates per device, sweeps at >= budget, resets only on a
successful sweep) rather than by arithmetic in my head; all call sites checked
for positional-argument binding; doc_comment_lint passes. Not compiled — Gradle
cannot run on this host (aapt2 is x86-64 only) and no CI job builds Android,
which is the same gap that let the regression sit on main for this long.
@ryanbr

ryanbr commented Jul 27, 2026

Copy link
Copy Markdown
Owner Author

android.yml is enabled now, and this branch has had a real build: assembleFullDebug and testFullDebugUnitTest both green (run).

That removes the "not compiled" caveat from the description. It confirms the defaulted parameters compile, and that the fixed test plus the two amortisation tests pass rather than just looking right. The branch is based on post-#902 main, so aapt2 also processed that PR's 22 new strings across six locales — the resource check I could not run locally either.

The workflow triggers on android/** for pull_request and push, so from here Android changes are covered without anyone remembering to dispatch.

@ryanbr
ryanbr merged commit d8fbe3e into main Jul 27, 2026
3 checks passed
@ryanbr
ryanbr deleted the fix/kotlin-v18aux-prune-test-parity branch July 27, 2026 22:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant