Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,23 +1,32 @@
package com.noop.testcentre

/**
* The report-completeness guard (Kotlin twin of the Swift ReportCompleteness). A report is only useful
* The report-completeness guard. Swift's architectural counterpart is `CaptureCompleteness` (there is no
* Swift type named ReportCompleteness). A report is only useful
* if the active mode's KILLER TRACE actually landed in report.txt. The Test Centre's whole point is that
* each domain emits one upfront, hard-to-miss line that settles the bug; if a tester toggles a mode but
* the emitter never fires (strap never connected, no scored day, the import never ran), the .zip looks
* full but carries nothing diagnostic. This guard reads report.txt back and reports, per active domain,
* whether its killer-trace token is present, so a maintainer (and the tester, via the review sheet) sees
* "Sleep: MISSING" before the report ships rather than after a round-trip.
*
* The {domain -> token} map below is the SINGLE source of truth and is byte-identical to the Swift twin
* (same domains, same token substrings). Each token is the distinctive, stable leading fragment of that
* The {domain -> token} map below is the SINGLE source of truth FOR THIS PLATFORM, and is deliberately
* NOT byte-identical to Swift's. It cannot be: each side keys on the tokens ITS OWN emitters actually
* write, and the two platforms word several of those lines differently. Of the ten killer tokens, four
* match Swift exactly, three differ only by a trailing fragment, and three have no counterpart in the
* Swift map at all -- import (`import parser=` vs `import stage=`), steps (`stepsEst ` vs `stepsRaw`)
* and battery (`battery series=` vs `bank soc=`). Aligning them would break this guard, because the
* token has to match the line Android emits. Each token is the distinctive, stable leading fragment of that
* domain's killer trace (verified against the trace emitters and their unit tests): a SUBSTRING match is
* deliberate so the per-day / per-record suffix (counts, ids, ISO dates) can vary without breaking the
* check. The UNIVERSAL token (`dayOwner day=`) rides every export, so it is checked on every report.
*
* Pure + side-effect-free (no clock, no IO): the assembler passes the assembled report.txt text and the
* active-domain set, and gets back the lines to append. No PII (tokens are fixed format fragments). No
* em-dashes. Tested directly on the JVM, and a parity test pins the map against the Swift twin.
* em-dashes. Tested directly on the JVM by ReportCompletenessContractTest, which pins THIS map -- it
* does not read the Swift side and cannot detect drift there. Cross-platform parity of the SECTION the
* user reads (labels, ordering, present/MISSING wording) is the contract that matters here; identical
* tokens are not, and were never achievable.
*/
object ReportCompleteness {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,23 @@ import org.junit.Assert.assertTrue
import org.junit.Test

/**
* Parity + behaviour test for the report-completeness guard. The {domain -> killer-token} map and the
* "Capture check" section labels MUST stay byte-identical to the Swift twin (the maintainer reads the
* same section on every platform), so this pins the map, the section text, and the present/MISSING logic.
* Contract + behaviour test for the report-completeness guard.
*
* NOT a parity test, despite what this file was called until #1531 exposed the difference. It pins the
* Kotlin {domain -> killer-token} map against literals held HERE; it never reads the Swift side, so it
* cannot fail when the two platforms drift -- and it stayed green through a divergence in which three of
* the ten tokens ended up with no Swift counterpart at all (import, steps, battery). Claiming otherwise
* was worse than claiming nothing, because it invited a reader to trust a guarantee that did not exist.
*
* What it DOES guarantee is still worth having: that Android's own map, section ordering and
* present/MISSING wording cannot change by accident. Identical tokens across platforms are neither the
* contract nor achievable -- each side must key on the lines its own emitters write. See
* ReportCompleteness's header for the per-domain breakdown.
*/
class ReportCompletenessParityTest {
class ReportCompletenessContractTest {

@Test fun killerTokenMapIsTheCanonicalContract() {
// Byte-identical to the Swift ReportCompleteness.killerTokens. UNIVERSAL plus the 9 wired domains;
// Android's own canonical map. UNIVERSAL plus the 9 wired domains;
// the Phase-3 domains (notifications/sources/stress/longevity) are intentionally absent.
assertEquals("dayOwner day=", ReportCompleteness.killerTokens[TestDomain.UNIVERSAL])
assertEquals("gate run=", ReportCompleteness.killerTokens[TestDomain.SLEEP])
Expand Down