PairedDeviceRevocationTest.kt

3.5 KB · raw

1package com.peachpasswords.sync23import org.junit.Assert.assertEquals4import org.junit.Assert.assertNull5import org.junit.Test67class PairedDeviceRevocationTest {8    private val browser = PairedDevice(9        deviceId = "browser-1",10        deviceName = "Chrome",11        deviceType = "extension",12        longTermPublicKeyHex = "ab".repeat(32),13        pairedAt = 1L,14    )1516    @Test17    fun `new revocation records the key and removes the paired row`() {18        val mutation = planDeviceRevocation(19            devices = listOf(browser),20            revocations = emptyList(),21            deviceId = browser.deviceId,22            revokedByDeviceId = "phone-1",23            nowMs = 42L,24        )2526        assertEquals(emptyList<PairedDevice>(), mutation.devices)27        assertEquals(1, mutation.revocations.size)28        assertEquals(browser.longTermPublicKeyHex, mutation.added?.longTermPublicKeyHex)29        assertEquals(42L, mutation.added?.revokedAt)30    }3132    @Test33    fun `full ledger keeps terminal records during peer merge capacity`() {34        val existing = List(500) { index ->35            DeviceRevocation("terminal-$index", index.toString(16).padStart(64, '0'), index.toLong(), "issuer-a")36        }37        val merged = mergeRevocationRecords(existing, listOf(38            DeviceRevocation("peer-extra", "ff".repeat(32), 501L, "issuer-b"),39        ))40        assertEquals(500, merged.records.size)41        assertEquals(0, merged.admitted.size)42        assertEquals("terminal-0", merged.records.first().deviceId)43    }4445    @Test46    fun `same issuer local flood uses bounded capacity`() {47        var records = emptyList<DeviceRevocation>()48        repeat(501) { index ->49            records = if (records.size < 500) records + DeviceRevocation("local-$index", index.toString(16).padStart(64, '0'), index.toLong(), "issuer-a")50            else records.drop(1) + DeviceRevocation("local-$index", index.toString(16).padStart(64, '0'), index.toLong(), "issuer-a")51        }52        assertEquals(500, records.size)53        assertEquals("local-1", records.first().deviceId)54        assertEquals("local-500", records.last().deviceId)55    }5657    @Test58    fun `different issuer local capacity preserves genuine issuer record`() {59        val existing = List(500) { index ->60            DeviceRevocation("terminal-$index", index.toString(16).padStart(64, '0'), index.toLong(), if (index == 0) "issuer-a" else "issuer-b")61        }62        val removable = existing.indexOfFirst { it.revokedByDeviceId != "issuer-a" }63        val records = existing.toMutableList().also { it.removeAt(removable); it += DeviceRevocation("local-new", "ff".repeat(32), 501L, "issuer-a") }64        assertEquals(500, records.size)65        assertEquals("terminal-0", records.first().deviceId)66        assertEquals("local-new", records.last().deviceId)67    }6869    @Test70    fun `existing revocation still removes a stale overlapping paired row`() {71        val existing = DeviceRevocation(72            deviceId = browser.deviceId,73            longTermPublicKeyHex = browser.longTermPublicKeyHex!!,74            revokedAt = 1L,75            revokedByDeviceId = "phone-1",76        )7778        val mutation = planDeviceRevocation(79            devices = listOf(browser),80            revocations = listOf(existing),81            deviceId = browser.deviceId,82            revokedByDeviceId = "phone-1",83            nowMs = 99L,84        )8586        assertEquals(emptyList<PairedDevice>(), mutation.devices)87        assertEquals(listOf(existing), mutation.revocations)88        assertNull(mutation.added)89    }90}