RelaySettingsPropagationTest.kt

3.0 KB · raw

1package com.peachpasswords.sync23import org.junit.Assert.assertEquals4import org.junit.Assert.assertSame5import org.junit.Test67/**8 * What a relay change does to the existing mesh, mirroring the browser's9 * `setSyncMode` / `setRelayUrl`. The store around this is only10 * EncryptedSharedPreferences and a Context this suite has no reason to stand11 * up; the decision it delegates to lives here.12 */13class RelaySettingsPropagationTest {14    private val selfHosted = "wss://relay.example.com"1516    private val pairs = listOf(17        PairedDevice(deviceId = "browser", relayUrl = "wss://old-relay.example", pairedAt = 1L),18        PairedDevice(deviceId = "phone", relayUrl = null, pairedAt = 2L),19    )2021    @Test22    fun `switching to private with an address moves every existing pair to it`() {23        val updated = withRelaySetting(pairs, SyncMode.PRIVATE, selfHosted)2425        assertEquals(listOf(selfHosted, selfHosted), updated.map { it.relayUrl })26        assertEquals(listOf("browser", "phone"), updated.map { it.deviceId })27    }2829    @Test30    fun `switching to public moves every existing pair back to peach's relay`() {31        val updated = withRelaySetting(pairs, SyncMode.PUBLIC, selfHosted)3233        assertEquals(34            listOf(Rendezvous.DEFAULT_RELAY_URL, Rendezvous.DEFAULT_RELAY_URL),35            updated.map { it.relayUrl },36        )37    }3839    /**40     * The exception. Private-with-no-address has nothing to push, and pushing41     * the stored default would put the whole mesh on Peach's relay under a42     * private label.43     */44    @Test45    fun `private with no address moves no pair`() {46        assertSame(pairs, withRelaySetting(pairs, SyncMode.PRIVATE, Rendezvous.DEFAULT_RELAY_URL))47    }4849    @Test50    fun `turning sync off leaves the mesh where it was`() {51        assertSame(pairs, withRelaySetting(pairs, SyncMode.OFF, selfHosted))52    }5354    /**55     * Adoption records the source's relay through the same path as the Settings56     * field, so what the Sync card then reads is [modeForRelayUrl] plus57     * [privateRelayUrlOf] over the adopted URL.58     */59    @Test60    fun `adoption over the public relay leaves the receiver reading public`() {61        val adopted = Rendezvous.DEFAULT_RELAY_URL6263        assertEquals(SyncMode.PUBLIC, modeForRelayUrl(adopted))64        assertEquals("", privateRelayUrlOf(adopted))65        assertEquals("wss://", privateRelayDraftOf(privateRelayUrlOf(adopted)))66    }6768    @Test69    fun `adoption over a private relay leaves the receiver reading that url`() {70        assertEquals(SyncMode.PRIVATE, modeForRelayUrl(selfHosted))71        assertEquals(selfHosted, privateRelayUrlOf(selfHosted))72        assertEquals(selfHosted, privateRelayDraftOf(privateRelayUrlOf(selfHosted)))73        // And the receiver is not stranded in the unconfigured-private state74        // that would pause its sync.75        assertEquals(76            RelayDecision.Dial(selfHosted),77            relayInForce(modeForRelayUrl(selfHosted), selfHosted),78        )79    }80}