1package com.peachpasswords.sync2345678internal class FakeSyncGeneration(9 var pairedDevices: Boolean = false,10 var revocations: Boolean = false,11 var issuerSigningKeys: Boolean = false,12 var pendingVouchedDevices: Boolean = false,13) : SyncGenerationPort {1415 var blob: String? = null16 private set1718 19 var failWrites: Boolean = false2021 22 var crashAt: String? = null2324 var archiveRef: String? = null25 private set26 var archiveCount: Int = 027 private set28 var cleared: Boolean = false29 private set30 var failArchive: Boolean = false31 var failClear: Boolean = false32 var failIdentity: Boolean = false33 var identityMints: Int = 034 private set35 var deviceId: String? = "anchor-device"3637 38 val calls = mutableListOf<String>()3940 val record: SyncGeneration?41 get() = blob?.let {42 runCatching { jsonForTest.decodeFromString<SyncGenerationBlob>(it).active }.getOrNull()43 }4445 override fun readBlob(): String? = blob4647 override fun writeBlob(blob: String): Boolean {48 if (failWrites) return false49 this.blob = blob50 return true51 }5253 override fun hasPairedDevices() = pairedDevices5455 override fun hasRevocations() = revocations5657 override fun hasIssuerSigningKeys() = issuerSigningKeys5859 override fun hasPendingVouchedDevices() = pendingVouchedDevices6061 override fun archiveLegacyState(generation: Int): String? {62 if (failArchive) return null63 archiveCount++64 archiveRef = "peach_sync_archive_v1"65 calls += "archive:$generation"66 return archiveRef67 }6869 override fun clearLegacyTrustState(): Boolean {70 if (failClear) return false71 cleared = true72 pairedDevices = false73 revocations = false74 issuerSigningKeys = false75 pendingVouchedDevices = false76 calls += "clear"77 return true78 }7980 override fun ensureV2Identity(): Boolean {81 if (failIdentity) return false82 identityMints++83 calls += "identity"84 return true85 }8687 override fun localDeviceId(): String? = deviceId8889 90 fun reset(nowMs: Long = 1_000L): ResetResult = confirmSecureReset(this, nowMs) { name ->91 if (name == crashAt) throw SimulatedCrash(name)92 }9394 class SimulatedCrash(name: String) : RuntimeException("crash at $name")95}9697private val jsonForTest = kotlinx.serialization.json.Json { ignoreUnknownKeys = true }9899100internal object EmptyRegistry : PairedDeviceRegistry {101 override fun getAll(): List<PairedDevice> = emptyList()102 override fun get(id: String): PairedDevice? = null103 override fun upsert(device: PairedDevice) = Unit104 override fun applyManifestBatch(batch: DeviceManifestRegistryBatch): Boolean = true105}