mirror of
https://github.com/signalapp/Signal-Android.git
synced 2026-02-26 04:33:36 +00:00
Add support for PNIs in storage service.
This commit is contained in:
committed by
Cody Henthorne
parent
cb057968ee
commit
95fc9d6c3c
@@ -0,0 +1,318 @@
|
||||
package org.thoughtcrime.securesms.storage
|
||||
|
||||
import org.junit.Assert.assertEquals
|
||||
import org.junit.Assert.assertFalse
|
||||
import org.junit.Assert.assertTrue
|
||||
import org.junit.BeforeClass
|
||||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
import org.mockito.Mock
|
||||
import org.mockito.MockedStatic
|
||||
import org.mockito.internal.configuration.plugins.Plugins
|
||||
import org.mockito.internal.junit.JUnitRule
|
||||
import org.mockito.junit.MockitoRule
|
||||
import org.mockito.quality.Strictness
|
||||
import org.signal.core.util.logging.Log
|
||||
import org.thoughtcrime.securesms.database.RecipientDatabase
|
||||
import org.thoughtcrime.securesms.testutil.EmptyLogger
|
||||
import org.thoughtcrime.securesms.util.FeatureFlags
|
||||
import org.whispersystems.signalservice.api.push.ACI
|
||||
import org.whispersystems.signalservice.api.push.PNI
|
||||
import org.whispersystems.signalservice.api.storage.SignalContactRecord
|
||||
import org.whispersystems.signalservice.api.storage.StorageId
|
||||
import org.whispersystems.signalservice.internal.storage.protos.ContactRecord
|
||||
import java.util.UUID
|
||||
|
||||
class ContactRecordProcessorTest {
|
||||
|
||||
@Rule
|
||||
@JvmField
|
||||
val mockitoRule: MockitoRule = JUnitRule(Plugins.getMockitoLogger(), Strictness.STRICT_STUBS)
|
||||
|
||||
@Mock
|
||||
lateinit var recipientDatabase: RecipientDatabase
|
||||
|
||||
@Mock
|
||||
lateinit var featureFlags: MockedStatic<FeatureFlags>
|
||||
|
||||
@Test
|
||||
fun `isInvalid, normal, false`() {
|
||||
// GIVEN
|
||||
val subject = ContactRecordProcessor(ACI_A, PNI_A, E164_A, recipientDatabase)
|
||||
|
||||
val record = buildRecord {
|
||||
setServiceId(ACI_B.toString())
|
||||
setServicePni(PNI_B.toString())
|
||||
setServiceE164(E164_B)
|
||||
}
|
||||
|
||||
// WHEN
|
||||
val result = subject.isInvalid(record)
|
||||
|
||||
// THEN
|
||||
assertFalse(result)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `isInvalid, missing serviceId, true`() {
|
||||
// GIVEN
|
||||
val subject = ContactRecordProcessor(ACI_A, PNI_A, E164_A, recipientDatabase)
|
||||
|
||||
val record = buildRecord {
|
||||
setServiceE164(E164_B)
|
||||
}
|
||||
|
||||
// WHEN
|
||||
val result = subject.isInvalid(record)
|
||||
|
||||
// THEN
|
||||
assertTrue(result)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `isInvalid, e164 matches self, true`() {
|
||||
// GIVEN
|
||||
val subject = ContactRecordProcessor(ACI_A, PNI_A, E164_A, recipientDatabase)
|
||||
|
||||
val record = buildRecord {
|
||||
setServiceId(ACI_B.toString())
|
||||
setServiceE164(E164_A)
|
||||
}
|
||||
|
||||
// WHEN
|
||||
val result = subject.isInvalid(record)
|
||||
|
||||
// THEN
|
||||
assertTrue(result)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `isInvalid, aci matches self, true`() {
|
||||
// GIVEN
|
||||
val subject = ContactRecordProcessor(ACI_A, PNI_A, E164_A, recipientDatabase)
|
||||
|
||||
val record = buildRecord {
|
||||
setServiceId(ACI_A.toString())
|
||||
}
|
||||
|
||||
// WHEN
|
||||
val result = subject.isInvalid(record)
|
||||
|
||||
// THEN
|
||||
assertTrue(result)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `isInvalid, pni matches self as serviceId, true`() {
|
||||
// GIVEN
|
||||
val subject = ContactRecordProcessor(ACI_A, PNI_A, E164_A, recipientDatabase)
|
||||
|
||||
val record = buildRecord {
|
||||
setServiceId(PNI_A.toString())
|
||||
}
|
||||
|
||||
// WHEN
|
||||
val result = subject.isInvalid(record)
|
||||
|
||||
// THEN
|
||||
assertTrue(result)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `isInvalid, pni matches self as pni, true`() {
|
||||
// GIVEN
|
||||
val subject = ContactRecordProcessor(ACI_A, PNI_A, E164_A, recipientDatabase)
|
||||
|
||||
val record = buildRecord {
|
||||
setServiceId(ACI_B.toString())
|
||||
setServicePni(PNI_A.toString())
|
||||
}
|
||||
|
||||
// WHEN
|
||||
val result = subject.isInvalid(record)
|
||||
|
||||
// THEN
|
||||
assertTrue(result)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `isInvalid, pniOnly pnpDisabled, true`() {
|
||||
// GIVEN
|
||||
val subject = ContactRecordProcessor(ACI_A, PNI_A, E164_A, recipientDatabase)
|
||||
|
||||
featureFlags.`when`<Boolean> { FeatureFlags.phoneNumberPrivacy() }.thenReturn(false)
|
||||
|
||||
val record = buildRecord {
|
||||
setServiceId(PNI_B.toString())
|
||||
setServicePni(PNI_B.toString())
|
||||
}
|
||||
|
||||
// WHEN
|
||||
val result = subject.isInvalid(record)
|
||||
|
||||
// THEN
|
||||
assertTrue(result)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `isInvalid, pniOnly pnpEnabled, false`() {
|
||||
// GIVEN
|
||||
val subject = ContactRecordProcessor(ACI_A, PNI_A, E164_A, recipientDatabase)
|
||||
|
||||
featureFlags.`when`<Boolean> { FeatureFlags.phoneNumberPrivacy() }.thenReturn(true)
|
||||
|
||||
val record = buildRecord {
|
||||
setServiceId(PNI_B.toString())
|
||||
setServicePni(PNI_B.toString())
|
||||
}
|
||||
|
||||
// WHEN
|
||||
val result = subject.isInvalid(record)
|
||||
|
||||
// THEN
|
||||
assertFalse(result)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `merge, e164MatchesButPnisDont pnpEnabled, keepLocal`() {
|
||||
// GIVEN
|
||||
val subject = ContactRecordProcessor(ACI_A, PNI_A, E164_A, recipientDatabase)
|
||||
|
||||
featureFlags.`when`<Boolean> { FeatureFlags.phoneNumberPrivacy() }.thenReturn(true)
|
||||
|
||||
val local = buildRecord(STORAGE_ID_A) {
|
||||
setServiceId(ACI_A.toString())
|
||||
setServiceE164(E164_A)
|
||||
setServicePni(PNI_A.toString())
|
||||
}
|
||||
|
||||
val remote = buildRecord(STORAGE_ID_B) {
|
||||
setServiceId(ACI_A.toString())
|
||||
setServiceE164(E164_A)
|
||||
setServicePni(PNI_B.toString())
|
||||
}
|
||||
|
||||
// WHEN
|
||||
val result = subject.merge(remote, local, TestKeyGenerator(STORAGE_ID_C))
|
||||
|
||||
// THEN
|
||||
assertEquals(local.serviceId, result.serviceId)
|
||||
assertEquals(local.number.get(), result.number.get())
|
||||
assertEquals(local.pni.get(), result.pni.get())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `merge, pnisMatchButE164sDont pnpEnabled, keepLocal`() {
|
||||
// GIVEN
|
||||
val subject = ContactRecordProcessor(ACI_A, PNI_A, E164_A, recipientDatabase)
|
||||
|
||||
featureFlags.`when`<Boolean> { FeatureFlags.phoneNumberPrivacy() }.thenReturn(true)
|
||||
|
||||
val local = buildRecord(STORAGE_ID_A) {
|
||||
setServiceId(ACI_A.toString())
|
||||
setServiceE164(E164_A)
|
||||
setServicePni(PNI_A.toString())
|
||||
}
|
||||
|
||||
val remote = buildRecord(STORAGE_ID_B) {
|
||||
setServiceId(ACI_A.toString())
|
||||
setServiceE164(E164_B)
|
||||
setServicePni(PNI_A.toString())
|
||||
}
|
||||
|
||||
// WHEN
|
||||
val result = subject.merge(remote, local, TestKeyGenerator(STORAGE_ID_C))
|
||||
|
||||
// THEN
|
||||
assertEquals(local.serviceId, result.serviceId)
|
||||
assertEquals(local.number.get(), result.number.get())
|
||||
assertEquals(local.pni.get(), result.pni.get())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `merge, e164AndPniChange pnpEnabled, useRemote`() {
|
||||
// GIVEN
|
||||
val subject = ContactRecordProcessor(ACI_A, PNI_A, E164_A, recipientDatabase)
|
||||
|
||||
featureFlags.`when`<Boolean> { FeatureFlags.phoneNumberPrivacy() }.thenReturn(true)
|
||||
|
||||
val local = buildRecord(STORAGE_ID_A) {
|
||||
setServiceId(ACI_A.toString())
|
||||
setServiceE164(E164_A)
|
||||
setServicePni(PNI_A.toString())
|
||||
}
|
||||
|
||||
val remote = buildRecord(STORAGE_ID_B) {
|
||||
setServiceId(ACI_A.toString())
|
||||
setServiceE164(E164_B)
|
||||
setServicePni(PNI_B.toString())
|
||||
}
|
||||
|
||||
// WHEN
|
||||
val result = subject.merge(remote, local, TestKeyGenerator(STORAGE_ID_C))
|
||||
|
||||
// THEN
|
||||
assertEquals(remote.serviceId, result.serviceId)
|
||||
assertEquals(remote.number.get(), result.number.get())
|
||||
assertEquals(remote.pni.get(), result.pni.get())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `merge, pnpDisabled, pniDropped`() {
|
||||
// GIVEN
|
||||
val subject = ContactRecordProcessor(ACI_A, PNI_A, E164_A, recipientDatabase)
|
||||
|
||||
featureFlags.`when`<Boolean> { FeatureFlags.phoneNumberPrivacy() }.thenReturn(false)
|
||||
|
||||
val local = buildRecord(STORAGE_ID_A) {
|
||||
setServiceId(ACI_A.toString())
|
||||
setServiceE164(E164_A)
|
||||
setServicePni(PNI_A.toString())
|
||||
}
|
||||
|
||||
val remote = buildRecord(STORAGE_ID_B) {
|
||||
setServiceId(ACI_A.toString())
|
||||
setServiceE164(E164_B)
|
||||
setServicePni(PNI_B.toString())
|
||||
}
|
||||
|
||||
// WHEN
|
||||
val result = subject.merge(remote, local, TestKeyGenerator(STORAGE_ID_C))
|
||||
|
||||
// THEN
|
||||
assertEquals(remote.serviceId, result.serviceId)
|
||||
assertEquals(remote.number.get(), result.number.get())
|
||||
assertEquals(false, result.pni.isPresent)
|
||||
}
|
||||
|
||||
private fun buildRecord(id: StorageId = STORAGE_ID_A, applyParams: ContactRecord.Builder.() -> ContactRecord.Builder): SignalContactRecord {
|
||||
return SignalContactRecord(id, ContactRecord.getDefaultInstance().toBuilder().applyParams().build())
|
||||
}
|
||||
|
||||
private class TestKeyGenerator(private val value: StorageId) : StorageKeyGenerator {
|
||||
override fun generate(): ByteArray {
|
||||
return value.raw
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
val STORAGE_ID_A: StorageId = StorageId.forStoryDistributionList(byteArrayOf(1, 2, 3, 4))
|
||||
val STORAGE_ID_B: StorageId = StorageId.forStoryDistributionList(byteArrayOf(5, 6, 7, 8))
|
||||
val STORAGE_ID_C: StorageId = StorageId.forStoryDistributionList(byteArrayOf(5, 6, 7, 8))
|
||||
|
||||
val ACI_A = ACI.from(UUID.fromString("3436efbe-5a76-47fa-a98a-7e72c948a82e"))
|
||||
val ACI_B = ACI.from(UUID.fromString("8de7f691-0b60-4a68-9cd9-ed2f8453f9ed"))
|
||||
|
||||
val PNI_A = PNI.from(UUID.fromString("154b8d92-c960-4f6c-8385-671ad2ffb999"))
|
||||
val PNI_B = PNI.from(UUID.fromString("ba92b1fb-cd55-40bf-adda-c35a85375533"))
|
||||
|
||||
const val E164_A = "+12221234567"
|
||||
const val E164_B = "+13331234567"
|
||||
|
||||
@JvmStatic
|
||||
@BeforeClass
|
||||
fun setUpClass() {
|
||||
Log.initialize(EmptyLogger())
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -176,7 +176,8 @@ public final class StorageSyncHelperTest {
|
||||
String e164,
|
||||
String profileName)
|
||||
{
|
||||
return new SignalContactRecord.Builder(byteArray(key), new SignalServiceAddress(aci, e164), null)
|
||||
return new SignalContactRecord.Builder(byteArray(key), aci, null)
|
||||
.setE164(e164)
|
||||
.setGivenName(profileName);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user