package com.peachpasswords.sync import org.junit.Assert.assertEquals import org.junit.Assert.assertFalse import org.junit.Assert.assertTrue import org.junit.Test import java.util.concurrent.CountDownLatch import java.util.concurrent.TimeUnit import kotlin.concurrent.thread class PairedDeviceStoreConcurrencyTest { @Test fun `a pairing snapshot cannot overwrite a concurrent sync update`() { val gate = RegistryMutationGate() val devices = mutableListOf("firefox") val pairingRead = CountDownLatch(1) val releasePairing = CountDownLatch(1) val syncEntered = CountDownLatch(1) val pairing = thread { gate.withLock { val snapshot = devices.toList() pairingRead.countDown() assertTrue(releasePairing.await(5, TimeUnit.SECONDS)) devices.clear() devices += snapshot + "chrome" } } assertTrue(pairingRead.await(5, TimeUnit.SECONDS)) val sync = thread { gate.withLock { syncEntered.countDown() val snapshot = devices.toList() devices.clear() devices += snapshot.map { if (it == "firefox") "firefox-synced" else it } } } assertFalse(syncEntered.await(100, TimeUnit.MILLISECONDS)) releasePairing.countDown() pairing.join(5_000) sync.join(5_000) assertEquals(setOf("firefox-synced", "chrome"), devices.toSet()) } }