SyncServiceStartTest.kt

2.5 KB · raw

1package com.peachpasswords.sync23import org.junit.Assert.assertEquals4import org.junit.Assert.assertTrue5import org.junit.Test67/**8 * The service start is the first step of every sync path, and it was the one9 * step that could throw straight out of a button press: Android 12+ refuses a10 * foreground service started from the background, and `startForegroundService`11 * was called bare.12 */13class SyncServiceStartTest {1415    /** The real thing on API 31+, whose class is not on this app's minSdk. */16    private fun backgroundStartRefused(): IllegalStateException = IllegalStateException(17        "Not allowed to start service Intent { cmp=com.peachpasswords/.sync.PeachSyncService }: " +18            "app is in background",19    )2021    @Test fun `a start Android refuses is reported, not thrown`() {22        val reported = mutableListOf<SyncOutcomeSummary>()23        val started = startOrReportBlocked({ reported += it }) { throw backgroundStartRefused() }2425        assertEquals(false, started)26        assertEquals(listOf(SyncOutcomeReason.FOREGROUND_START_BLOCKED), reported.map { it.reason })27        assertTrue(reported.single().detail?.contains("app is in background") == true)28    }2930    @Test fun `the refusal says what the person holding the phone can do`() {31        assertEquals(32            "Android blocked Peach from starting sync in the background — open Peach and sync again",33            describeSyncOutcome(SyncOutcomeSummary(reason = SyncOutcomeReason.FOREGROUND_START_BLOCKED)),34        )35        assertEquals(36            SyncIndicator.ERROR,37            syncIndicator(38                SyncOutcomeSummary(reason = SyncOutcomeReason.FOREGROUND_START_BLOCKED),39                pairedCount = 1,40            ),41        )42    }4344    /** A start that fails some other way is still a sync that did not happen. */45    @Test fun `anything else the platform throws is reported too, and never escapes`() {46        val reported = mutableListOf<SyncOutcomeSummary>()47        val started = startOrReportBlocked({ reported += it }) {48            throw SecurityException("missing FOREGROUND_SERVICE_DATA_SYNC")49        }5051        assertEquals(false, started)52        assertEquals(listOf(SyncOutcomeReason.RUN_FAILED), reported.map { it.reason })53    }5455    @Test fun `a start that works reports nothing`() {56        val reported = mutableListOf<SyncOutcomeSummary>()57        var ran = false5859        assertEquals(true, startOrReportBlocked({ reported += it }) { ran = true })60        assertTrue(ran)61        assertTrue(reported.isEmpty())62    }63}