36feed1efeba
test: pin clean-close string + dialer cooldown spec (v2.9.16)
- time
- 2026-07-31 10:50 UTC · 2 months ago
- machine
- koh2
- parent
- 877dd0a16304
↓ peach-android-36feed1e.tar.gzatlas at this save
files changed3 files
VERSION+1 −1app/src/main/java/com/peachpasswords/sync/CloudRelayReconnectListener.kt+4 −1app/src/test/java/com/peachpasswords/sync/CloudRelayReconnectListenerTest.kt+24 −0app/src/main/java/com/peachpasswords/sync/CloudRelayReconnectListener.kt+4 −1
@@ -88,6 +88,9 @@8888 error.message?.takeIf { it.isNotBlank() } ?: error.javaClass.simpleName,8989 )9090 91+internal fun relaySocketCloseReason(error: Throwable?): String =92+ error?.let(::relayLogReason) ?: "relay session complete"93+9194 internal data class RelayReconcileInventory(9295 val paired: List<PairedDevice>,9396 val eligible: List<PairedDevice>,@@ -447,7 +450,7 @@447450 )448451 449452 private fun logRelaySocketClosed(error: Throwable?) {450- val reason = error?.let(::relayLogReason) ?: "relay session complete"453+ val reason = relaySocketCloseReason(error)451454 val outcome = error?.let { classifySyncError(reason) }452455 val message = "cloud-relay: socket closed — reason=$reason"453456 when {app/src/test/java/com/peachpasswords/sync/CloudRelayReconnectListenerTest.kt+24 −0
@@ -78,6 +78,30 @@7878 }7979 8080 @Test81+ fun `clean socket close reason is the literal "relay session complete" string`() {82+ // Presence of this exact string in logcat is how we grep for a successful83+ // sync close-out. Anything else (a renamed literal, a swallowed exception)84+ // breaks that grep and the avoidable idle-burn diagnosis.85+ assertEquals("relay session complete", relaySocketCloseReason(error = null))86+ assertEquals(87+ "session ended by peer",88+ relaySocketCloseReason(error = RuntimeException("session ended by peer")),89+ )90+ }91+92+ @Test93+ fun `clean-complete dial ramps the dialer cooldown above the reconcile hot loop`() {94+ // After a clean "relay session complete" close, the dialer would otherwise95+ // re-dial at the reconcile cadence (DIAL_RETRY_DELAY_MS=5_000). That is the96+ // idle-burn visible in logcat: a 20s ping/pong timeout per cycle. The fix97+ // must keep the next dial well outside the hot loop. Floor: 2x.98+ assertTrue(99+ "expected clean-complete dialer cooldown >= 10_000 (2x the 5_000 hot loop)",100+ nextRelayRetryDelay(current = 5_000L, succeeded = true, dialer = true) >= 10_000L,101+ )102+ }103+104+ @Test81105 fun `reconcile logs paired and eligible counts when no peer passes the filter`() = runBlocking {82106 val devices = listOf(83107 PairedDevice(