Strongly type UUIDs as ACIs.

This commit is contained in:
Greyson Parrelli
2021-10-28 15:39:36 -04:00
parent 6c7d837964
commit 5bb48caafd
120 changed files with 1020 additions and 947 deletions

View File

@@ -3,13 +3,13 @@ package org.thoughtcrime.securesms.contacts.sync;
import org.junit.Test;
import org.thoughtcrime.securesms.contacts.sync.FuzzyPhoneNumberHelper.InputResult;
import org.thoughtcrime.securesms.contacts.sync.FuzzyPhoneNumberHelper.OutputResult;
import org.whispersystems.signalservice.api.push.ACI;
import org.whispersystems.signalservice.api.util.UuidUtil;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import java.util.UUID;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
@@ -23,8 +23,8 @@ public class FuzzyPhoneNumberHelperTest {
private static final String MX_A = "+525512345678";
private static final String MX_A_1 = "+5215512345678";
private static final UUID UUID_A = UuidUtil.parseOrThrow("db980097-1e02-452f-9937-899630508705");
private static final UUID UUID_B = UuidUtil.parseOrThrow("11ccd6de-8fcc-49d6-bb9e-df21ff88bd6f");
private static final ACI ACI_A = ACI.parseOrThrow("db980097-1e02-452f-9937-899630508705");
private static final ACI ACI_B = ACI.parseOrThrow("11ccd6de-8fcc-49d6-bb9e-df21ff88bd6f");
@Test
public void generateInput_noMxNumbers() {
@@ -100,65 +100,65 @@ public class FuzzyPhoneNumberHelperTest {
@Test
public void generateOutput_noMxNumbers() {
OutputResult result = FuzzyPhoneNumberHelper.generateOutput(mapOf(US_A, UUID_A, US_B, UUID_B), new InputResult(setOf(US_A, US_B), Collections.emptyMap()));
OutputResult result = FuzzyPhoneNumberHelper.generateOutput(mapOf(US_A, ACI_A, US_B, ACI_B), new InputResult(setOf(US_A, US_B), Collections.emptyMap()));
assertEquals(2, result.getNumbers().size());
assertEquals(UUID_A, result.getNumbers().get(US_A));
assertEquals(UUID_B, result.getNumbers().get(US_B));
assertEquals(ACI_A, result.getNumbers().get(US_A));
assertEquals(ACI_B, result.getNumbers().get(US_B));
assertTrue(result.getRewrites().isEmpty());
}
@Test
public void generateOutput_bothMatch_no1To1() {
OutputResult result = FuzzyPhoneNumberHelper.generateOutput(mapOf(MX_A, UUID_A, MX_A_1, UUID_B), new InputResult(setOf(MX_A, MX_A_1), Collections.singletonMap(MX_A, MX_A_1)));
OutputResult result = FuzzyPhoneNumberHelper.generateOutput(mapOf(MX_A, ACI_A, MX_A_1, ACI_B), new InputResult(setOf(MX_A, MX_A_1), Collections.singletonMap(MX_A, MX_A_1)));
assertEquals(1, result.getNumbers().size());
assertEquals(UUID_A, result.getNumbers().get(MX_A));
assertEquals(ACI_A, result.getNumbers().get(MX_A));
assertTrue(result.getRewrites().isEmpty());
}
@Test
public void generateOutput_bothMatch_1toNo1() {
OutputResult result = FuzzyPhoneNumberHelper.generateOutput(mapOf(MX_A, UUID_A, MX_A_1, UUID_B), new InputResult(setOf(MX_A, MX_A_1), Collections.singletonMap(MX_A_1, MX_A)));
OutputResult result = FuzzyPhoneNumberHelper.generateOutput(mapOf(MX_A, ACI_A, MX_A_1, ACI_B), new InputResult(setOf(MX_A, MX_A_1), Collections.singletonMap(MX_A_1, MX_A)));
assertEquals(1, result.getNumbers().size());
assertEquals(UUID_A, result.getNumbers().get(MX_A));
assertEquals(ACI_A, result.getNumbers().get(MX_A));
assertEquals(MX_A, result.getRewrites().get(MX_A_1));
}
@Test
public void generateOutput_no1Match_no1To1() {
OutputResult result = FuzzyPhoneNumberHelper.generateOutput(mapOf(MX_A, UUID_A), new InputResult(setOf(MX_A, MX_A_1), Collections.singletonMap(MX_A, MX_A_1)));
OutputResult result = FuzzyPhoneNumberHelper.generateOutput(mapOf(MX_A, ACI_A), new InputResult(setOf(MX_A, MX_A_1), Collections.singletonMap(MX_A, MX_A_1)));
assertEquals(1, result.getNumbers().size());
assertEquals(UUID_A, result.getNumbers().get(MX_A));
assertEquals(ACI_A, result.getNumbers().get(MX_A));
assertTrue(result.getRewrites().isEmpty());
}
@Test
public void generateOutput_no1Match_1ToNo1() {
OutputResult result = FuzzyPhoneNumberHelper.generateOutput(mapOf(MX_A, UUID_A), new InputResult(setOf(MX_A, MX_A_1), Collections.singletonMap(MX_A_1, MX_A)));
OutputResult result = FuzzyPhoneNumberHelper.generateOutput(mapOf(MX_A, ACI_A), new InputResult(setOf(MX_A, MX_A_1), Collections.singletonMap(MX_A_1, MX_A)));
assertEquals(1, result.getNumbers().size());
assertEquals(UUID_A, result.getNumbers().get(MX_A));
assertEquals(ACI_A, result.getNumbers().get(MX_A));
assertEquals(MX_A, result.getRewrites().get(MX_A_1));
}
@Test
public void generateOutput_1Match_1ToNo1() {
OutputResult result = FuzzyPhoneNumberHelper.generateOutput(mapOf(MX_A_1, UUID_A), new InputResult(setOf(MX_A, MX_A_1), Collections.singletonMap(MX_A_1, MX_A)));
OutputResult result = FuzzyPhoneNumberHelper.generateOutput(mapOf(MX_A_1, ACI_A), new InputResult(setOf(MX_A, MX_A_1), Collections.singletonMap(MX_A_1, MX_A)));
assertEquals(1, result.getNumbers().size());
assertEquals(UUID_A, result.getNumbers().get(MX_A_1));
assertEquals(ACI_A, result.getNumbers().get(MX_A_1));
assertTrue(result.getRewrites().isEmpty());
}
@Test
public void generateOutput_1Match_no1To1() {
OutputResult result = FuzzyPhoneNumberHelper.generateOutput(mapOf(MX_A_1, UUID_A), new InputResult(setOf(MX_A, MX_A_1), Collections.singletonMap(MX_A, MX_A_1)));
OutputResult result = FuzzyPhoneNumberHelper.generateOutput(mapOf(MX_A_1, ACI_A), new InputResult(setOf(MX_A, MX_A_1), Collections.singletonMap(MX_A, MX_A_1)));
assertEquals(1, result.getNumbers().size());
assertEquals(UUID_A, result.getNumbers().get(MX_A_1));
assertEquals(ACI_A, result.getNumbers().get(MX_A_1));
assertEquals(MX_A_1, result.getRewrites().get(MX_A));
}

View File

@@ -12,6 +12,7 @@ import org.thoughtcrime.securesms.recipients.RecipientDetails
import org.thoughtcrime.securesms.recipients.RecipientId
import org.thoughtcrime.securesms.wallpaper.ChatWallpaper
import org.whispersystems.libsignal.util.guava.Optional
import org.whispersystems.signalservice.api.push.ACI
import java.util.UUID
import kotlin.random.Random
@@ -28,7 +29,7 @@ object RecipientDatabaseTestUtils {
isSelf: Boolean = false,
participants: List<Recipient> = listOf(),
recipientId: RecipientId = RecipientId.from(Random.nextLong()),
uuid: UUID? = UUID.randomUUID(),
aci: ACI? = ACI.from(UUID.randomUUID()),
username: String? = null,
e164: String? = null,
email: String? = null,
@@ -89,7 +90,7 @@ object RecipientDatabaseTestUtils {
registered,
RecipientDatabase.RecipientSettings(
recipientId,
uuid,
aci,
username,
e164,
email,

View File

@@ -25,13 +25,14 @@ import org.signal.storageservice.protos.groups.local.DecryptedGroupChange;
import org.signal.storageservice.protos.groups.local.DecryptedMember;
import org.signal.storageservice.protos.groups.local.DecryptedPendingMember;
import org.thoughtcrime.securesms.testutil.MainThreadUtil;
import org.thoughtcrime.securesms.util.Util;
import org.whispersystems.signalservice.api.push.ACI;
import org.whispersystems.signalservice.api.util.UuidUtil;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.stream.Collectors;
import static java.util.Collections.emptyList;
import static java.util.Collections.singletonList;
@@ -1350,12 +1351,14 @@ public final class GroupsV2UpdateMessageProducerTest {
}
private void assertSingleChangeMentioning(DecryptedGroupChange change, List<UUID> expectedMentions) {
List<ACI> expectedMentionAcis = expectedMentions.stream().map(ACI::from).collect(Collectors.toList());
List<UpdateDescription> changes = producer.describeChanges(null, change);
assertThat(changes.size(), is(1));
UpdateDescription description = changes.get(0);
assertThat(description.getMentioned(), is(expectedMentions));
assertThat(description.getMentioned(), is(expectedMentionAcis));
if (expectedMentions.isEmpty()) {
assertTrue(description.isStringStatic());
@@ -1394,8 +1397,8 @@ public final class GroupsV2UpdateMessageProducerTest {
}
private static @NonNull GroupsV2UpdateMessageProducer.DescribeMemberStrategy createDescriber(@NonNull Map<UUID, String> map) {
return uuid -> {
String name = map.get(uuid);
return aci -> {
String name = map.get(aci.uuid());
assertNotNull(name);
return name;
};

View File

@@ -6,6 +6,7 @@ import org.junit.runner.RunWith;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
import org.signal.core.util.ThreadUtil;
import org.whispersystems.signalservice.api.push.ACI;
import java.util.Arrays;
import java.util.Collections;
@@ -50,7 +51,7 @@ public final class UpdateDescriptionTest {
@Test(expected = AssertionError.class)
public void stringFactory_cannot_run_on_main_thread() {
UpdateDescription description = UpdateDescription.mentioning(Collections.singletonList(UUID.randomUUID()), () -> "update", 0);
UpdateDescription description = UpdateDescription.mentioning(Collections.singletonList(ACI.from(UUID.randomUUID())), () -> "update", 0);
setMainThread(true);
@@ -59,7 +60,7 @@ public final class UpdateDescriptionTest {
@Test(expected = UnsupportedOperationException.class)
public void stringFactory_cannot_call_static_string() {
UpdateDescription description = UpdateDescription.mentioning(Collections.singletonList(UUID.randomUUID()), () -> "update", 0);
UpdateDescription description = UpdateDescription.mentioning(Collections.singletonList(ACI.from(UUID.randomUUID())), () -> "update", 0);
description.getStaticString();
}
@@ -73,7 +74,7 @@ public final class UpdateDescriptionTest {
return "update";
};
UpdateDescription description = UpdateDescription.mentioning(Collections.singletonList(UUID.randomUUID()), stringFactory, 0);
UpdateDescription description = UpdateDescription.mentioning(Collections.singletonList(ACI.from(UUID.randomUUID())), stringFactory, 0);
assertEquals(0, factoryCalls.get());
@@ -89,7 +90,7 @@ public final class UpdateDescriptionTest {
public void stringFactory_reevaluated_on_every_call() {
AtomicInteger factoryCalls = new AtomicInteger();
UpdateDescription.StringFactory stringFactory = () -> "call" + factoryCalls.incrementAndGet();
UpdateDescription description = UpdateDescription.mentioning(Collections.singletonList(UUID.randomUUID()), stringFactory, 0);
UpdateDescription description = UpdateDescription.mentioning(Collections.singletonList(ACI.from(UUID.randomUUID())), stringFactory, 0);
setMainThread(false);
@@ -125,8 +126,8 @@ public final class UpdateDescriptionTest {
AtomicInteger factoryCalls2 = new AtomicInteger();
UpdateDescription.StringFactory stringFactory1 = () -> "update." + factoryCalls1.incrementAndGet();
UpdateDescription.StringFactory stringFactory2 = () -> "update." + factoryCalls2.incrementAndGet();
UpdateDescription description1 = UpdateDescription.mentioning(Collections.singletonList(UUID.randomUUID()), stringFactory1, 0);
UpdateDescription description2 = UpdateDescription.mentioning(Collections.singletonList(UUID.randomUUID()), stringFactory2, 0);
UpdateDescription description1 = UpdateDescription.mentioning(Collections.singletonList(ACI.from(UUID.randomUUID())), stringFactory1, 0);
UpdateDescription description2 = UpdateDescription.mentioning(Collections.singletonList(ACI.from(UUID.randomUUID())), stringFactory2, 0);
factoryCalls1.set(10);
factoryCalls2.set(20);
@@ -148,9 +149,9 @@ public final class UpdateDescriptionTest {
AtomicInteger factoryCalls2 = new AtomicInteger();
UpdateDescription.StringFactory stringFactory1 = () -> "update." + factoryCalls1.incrementAndGet();
UpdateDescription.StringFactory stringFactory2 = () -> "update." + factoryCalls2.incrementAndGet();
UpdateDescription description1 = UpdateDescription.mentioning(Collections.singletonList(UUID.randomUUID()), stringFactory1, 0);
UpdateDescription description1 = UpdateDescription.mentioning(Collections.singletonList(ACI.from(UUID.randomUUID())), stringFactory1, 0);
UpdateDescription description2 = UpdateDescription.staticDescription("static", 0);
UpdateDescription description3 = UpdateDescription.mentioning(Collections.singletonList(UUID.randomUUID()), stringFactory2, 0);
UpdateDescription description3 = UpdateDescription.mentioning(Collections.singletonList(ACI.from(UUID.randomUUID())), stringFactory2, 0);
factoryCalls1.set(100);
factoryCalls2.set(200);

View File

@@ -5,6 +5,7 @@ import org.signal.core.util.logging.Log;
import org.signal.zkgroup.profiles.ProfileKey;
import org.thoughtcrime.securesms.crypto.ProfileKeyUtil;
import org.thoughtcrime.securesms.testutil.LogRecorder;
import org.whispersystems.signalservice.api.push.ACI;
import java.util.Collections;
import java.util.UUID;
@@ -39,7 +40,7 @@ public final class ProfileKeySetTest {
profileKeySet.addKeysFromGroupChange(changeBy(editor).addMember(newMember, profileKey).build());
assertTrue(profileKeySet.getAuthoritativeProfileKeys().isEmpty());
assertThat(profileKeySet.getProfileKeys(), is(Collections.singletonMap(newMember, profileKey)));
assertThat(profileKeySet.getProfileKeys(), is(Collections.singletonMap(ACI.from(newMember), profileKey)));
}
@Test
@@ -51,7 +52,7 @@ public final class ProfileKeySetTest {
profileKeySet.addKeysFromGroupChange(changeBy(newMember).addMember(newMember, profileKey).build());
assertTrue(profileKeySet.getProfileKeys().isEmpty());
assertThat(profileKeySet.getAuthoritativeProfileKeys(), is(Collections.singletonMap(newMember, profileKey)));
assertThat(profileKeySet.getAuthoritativeProfileKeys(), is(Collections.singletonMap(ACI.from(newMember), profileKey)));
}
@Test
@@ -63,7 +64,7 @@ public final class ProfileKeySetTest {
profileKeySet.addKeysFromGroupChange(changeBy(newMember).promote(newMember, profileKey).build());
assertTrue(profileKeySet.getProfileKeys().isEmpty());
assertThat(profileKeySet.getAuthoritativeProfileKeys(), is(Collections.singletonMap(newMember, profileKey)));
assertThat(profileKeySet.getAuthoritativeProfileKeys(), is(Collections.singletonMap(ACI.from(newMember), profileKey)));
}
@Test
@@ -76,7 +77,7 @@ public final class ProfileKeySetTest {
profileKeySet.addKeysFromGroupChange(changeBy(editor).promote(newMember, profileKey).build());
assertTrue(profileKeySet.getAuthoritativeProfileKeys().isEmpty());
assertThat(profileKeySet.getProfileKeys(), is(Collections.singletonMap(newMember, profileKey)));
assertThat(profileKeySet.getProfileKeys(), is(Collections.singletonMap(ACI.from(newMember), profileKey)));
}
@Test
@@ -88,7 +89,7 @@ public final class ProfileKeySetTest {
profileKeySet.addKeysFromGroupChange(changeByUnknown().promote(newMember, profileKey).build());
assertTrue(profileKeySet.getAuthoritativeProfileKeys().isEmpty());
assertThat(profileKeySet.getProfileKeys(), is(Collections.singletonMap(newMember, profileKey)));
assertThat(profileKeySet.getProfileKeys(), is(Collections.singletonMap(ACI.from(newMember), profileKey)));
}
@Test
@@ -100,7 +101,7 @@ public final class ProfileKeySetTest {
profileKeySet.addKeysFromGroupChange(changeBy(member).profileKeyUpdate(member, profileKey).build());
assertTrue(profileKeySet.getProfileKeys().isEmpty());
assertThat(profileKeySet.getAuthoritativeProfileKeys(), is(Collections.singletonMap(member, profileKey)));
assertThat(profileKeySet.getAuthoritativeProfileKeys(), is(Collections.singletonMap(ACI.from(member), profileKey)));
}
@Test
@@ -113,7 +114,7 @@ public final class ProfileKeySetTest {
profileKeySet.addKeysFromGroupChange(changeBy(editor).profileKeyUpdate(member, profileKey).build());
assertTrue(profileKeySet.getAuthoritativeProfileKeys().isEmpty());
assertThat(profileKeySet.getProfileKeys(), is(Collections.singletonMap(member, profileKey)));
assertThat(profileKeySet.getProfileKeys(), is(Collections.singletonMap(ACI.from(member), profileKey)));
}
@Test
@@ -128,7 +129,7 @@ public final class ProfileKeySetTest {
profileKeySet.addKeysFromGroupChange(changeBy(editor).profileKeyUpdate(member, profileKey2).build());
assertTrue(profileKeySet.getAuthoritativeProfileKeys().isEmpty());
assertThat(profileKeySet.getProfileKeys(), is(Collections.singletonMap(member, profileKey2)));
assertThat(profileKeySet.getProfileKeys(), is(Collections.singletonMap(ACI.from(member), profileKey2)));
}
@Test
@@ -143,7 +144,7 @@ public final class ProfileKeySetTest {
profileKeySet.addKeysFromGroupChange(changeBy(editor).profileKeyUpdate(member, profileKey2).build());
assertTrue(profileKeySet.getProfileKeys().isEmpty());
assertThat(profileKeySet.getAuthoritativeProfileKeys(), is(Collections.singletonMap(member, profileKey1)));
assertThat(profileKeySet.getAuthoritativeProfileKeys(), is(Collections.singletonMap(ACI.from(member), profileKey1)));
}
@Test
@@ -158,7 +159,7 @@ public final class ProfileKeySetTest {
profileKeySet.addKeysFromGroupChange(changeBy(member).profileKeyUpdate(member, profileKey2).build());
assertTrue(profileKeySet.getProfileKeys().isEmpty());
assertThat(profileKeySet.getAuthoritativeProfileKeys(), is(Collections.singletonMap(member, profileKey2)));
assertThat(profileKeySet.getAuthoritativeProfileKeys(), is(Collections.singletonMap(ACI.from(member), profileKey2)));
}
@Test
@@ -185,7 +186,7 @@ public final class ProfileKeySetTest {
profileKeySet.addKeysFromGroupChange(changeBy(editor).requestJoin(profileKey).build());
assertThat(profileKeySet.getAuthoritativeProfileKeys(), is(Collections.singletonMap(editor, profileKey)));
assertThat(profileKeySet.getAuthoritativeProfileKeys(), is(Collections.singletonMap(ACI.from(editor), profileKey)));
assertTrue(profileKeySet.getProfileKeys().isEmpty());
}
@@ -199,6 +200,6 @@ public final class ProfileKeySetTest {
profileKeySet.addKeysFromGroupChange(changeBy(editor).requestJoin(requesting, profileKey).build());
assertTrue(profileKeySet.getAuthoritativeProfileKeys().isEmpty());
assertThat(profileKeySet.getProfileKeys(), is(Collections.singletonMap(requesting, profileKey)));
assertThat(profileKeySet.getProfileKeys(), is(Collections.singletonMap(ACI.from(requesting), profileKey)));
}
}

View File

@@ -8,6 +8,7 @@ import org.junit.Test;
import org.signal.core.util.logging.Log;
import org.thoughtcrime.securesms.testutil.LogRecorder;
import org.whispersystems.libsignal.util.guava.Optional;
import org.whispersystems.signalservice.api.push.ACI;
import java.util.UUID;
@@ -39,7 +40,7 @@ public final class RecipientIdCacheTest {
@Test
public void empty_access_by_uuid() {
RecipientId recipientId = recipientIdCache.get(UUID.randomUUID(), null);
RecipientId recipientId = recipientIdCache.get(ACI.from(UUID.randomUUID()), null);
assertNull(recipientId);
}
@@ -54,11 +55,11 @@ public final class RecipientIdCacheTest {
@Test
public void cache_hit_by_uuid() {
RecipientId recipientId1 = recipientId();
UUID uuid1 = UUID.randomUUID();
ACI aci1 = ACI.from(UUID.randomUUID());
recipientIdCache.put(recipient(recipientId1, uuid1, null));
recipientIdCache.put(recipient(recipientId1, aci1, null));
RecipientId recipientId = recipientIdCache.get(uuid1, null);
RecipientId recipientId = recipientIdCache.get(aci1, null);
assertEquals(recipientId1, recipientId);
}
@@ -66,12 +67,12 @@ public final class RecipientIdCacheTest {
@Test
public void cache_miss_by_uuid() {
RecipientId recipientId1 = recipientId();
UUID uuid1 = UUID.randomUUID();
UUID uuid2 = UUID.randomUUID();
ACI aci1 = ACI.from(UUID.randomUUID());
ACI aci2 = ACI.from(UUID.randomUUID());
recipientIdCache.put(recipient(recipientId1, uuid1, null));
recipientIdCache.put(recipient(recipientId1, aci1, null));
RecipientId recipientId = recipientIdCache.get(uuid2, null);
RecipientId recipientId = recipientIdCache.get(aci2, null);
assertNull(recipientId);
}
@@ -79,11 +80,11 @@ public final class RecipientIdCacheTest {
@Test
public void cache_hit_by_uuid_e164_not_supplied_on_get() {
RecipientId recipientId1 = recipientId();
UUID uuid1 = UUID.randomUUID();
ACI aci1 = ACI.from(UUID.randomUUID());
recipientIdCache.put(recipient(recipientId1, uuid1, "+15551234567"));
recipientIdCache.put(recipient(recipientId1, aci1, "+15551234567"));
RecipientId recipientId = recipientIdCache.get(uuid1, null);
RecipientId recipientId = recipientIdCache.get(aci1, null);
assertEquals(recipientId1, recipientId);
}
@@ -91,11 +92,11 @@ public final class RecipientIdCacheTest {
@Test
public void cache_miss_by_uuid_e164_not_supplied_on_put() {
RecipientId recipientId1 = recipientId();
UUID uuid1 = UUID.randomUUID();
ACI aci1 = ACI.from(UUID.randomUUID());
recipientIdCache.put(recipient(recipientId1, uuid1, null));
recipientIdCache.put(recipient(recipientId1, aci1, null));
RecipientId recipientId = recipientIdCache.get(uuid1, "+15551234567");
RecipientId recipientId = recipientIdCache.get(aci1, "+15551234567");
assertNull(recipientId);
}
@@ -128,9 +129,9 @@ public final class RecipientIdCacheTest {
@Test
public void cache_hit_by_e164_uuid_not_supplied_on_get() {
RecipientId recipientId1 = recipientId();
UUID uuid1 = UUID.randomUUID();
ACI aci1 = ACI.from(UUID.randomUUID());
recipientIdCache.put(recipient(recipientId1, uuid1, "+15551234567"));
recipientIdCache.put(recipient(recipientId1, aci1, "+15551234567"));
RecipientId recipientId = recipientIdCache.get(null, "+15551234567");
@@ -140,12 +141,12 @@ public final class RecipientIdCacheTest {
@Test
public void cache_miss_by_e164_uuid_not_supplied_on_put() {
RecipientId recipientId1 = recipientId();
UUID uuid1 = UUID.randomUUID();
ACI aci1 = ACI.from(UUID.randomUUID());
String e164 = "+1555123456";
recipientIdCache.put(recipient(recipientId1, null, e164));
RecipientId recipientId = recipientIdCache.get(uuid1, e164);
RecipientId recipientId = recipientIdCache.get(aci1, e164);
assertNull(recipientId);
}
@@ -153,12 +154,12 @@ public final class RecipientIdCacheTest {
@Test
public void cache_hit_by_both() {
RecipientId recipientId1 = recipientId();
UUID uuid1 = UUID.randomUUID();
ACI aci1 = ACI.from(UUID.randomUUID());
String e164 = "+1555123456";
recipientIdCache.put(recipient(recipientId1, uuid1, e164));
recipientIdCache.put(recipient(recipientId1, aci1, e164));
RecipientId recipientId = recipientIdCache.get(uuid1, e164);
RecipientId recipientId = recipientIdCache.get(aci1, e164);
assertEquals(recipientId1, recipientId);
}
@@ -166,13 +167,13 @@ public final class RecipientIdCacheTest {
@Test
public void full_recipient_id_learned_by_two_puts() {
RecipientId recipientId1 = recipientId();
UUID uuid1 = UUID.randomUUID();
ACI aci1 = ACI.from(UUID.randomUUID());
String e164 = "+1555123456";
recipientIdCache.put(recipient(recipientId1, uuid1, null));
recipientIdCache.put(recipient(recipientId1, aci1, null));
recipientIdCache.put(recipient(recipientId1, null, e164));
RecipientId recipientId = recipientIdCache.get(uuid1, e164);
RecipientId recipientId = recipientIdCache.get(aci1, e164);
assertEquals(recipientId1, recipientId);
}
@@ -181,13 +182,13 @@ public final class RecipientIdCacheTest {
public void if_cache_state_disagrees_returns_null() {
RecipientId recipientId1 = recipientId();
RecipientId recipientId2 = recipientId();
UUID uuid = UUID.randomUUID();
ACI aci = ACI.from(UUID.randomUUID());
String e164 = "+1555123456";
recipientIdCache.put(recipient(recipientId1, null, e164));
recipientIdCache.put(recipient(recipientId2, uuid, null));
recipientIdCache.put(recipient(recipientId2, aci, null));
RecipientId recipientId = recipientIdCache.get(uuid, e164);
RecipientId recipientId = recipientIdCache.get(aci, e164);
assertNull(recipientId);
@@ -199,15 +200,15 @@ public final class RecipientIdCacheTest {
public void after_invalid_cache_hit_entries_are_cleared_up() {
RecipientId recipientId1 = recipientId();
RecipientId recipientId2 = recipientId();
UUID uuid = UUID.randomUUID();
ACI aci = ACI.from(UUID.randomUUID());
String e164 = "+1555123456";
recipientIdCache.put(recipient(recipientId1, null, e164));
recipientIdCache.put(recipient(recipientId2, uuid, null));
recipientIdCache.put(recipient(recipientId2, aci, null));
recipientIdCache.get(uuid, e164);
recipientIdCache.get(aci, e164);
assertNull(recipientIdCache.get(uuid, null));
assertNull(recipientIdCache.get(aci, null));
assertNull(recipientIdCache.get(null, e164));
}
@@ -215,57 +216,57 @@ public final class RecipientIdCacheTest {
public void multiple_entries() {
RecipientId recipientId1 = recipientId();
RecipientId recipientId2 = recipientId();
UUID uuid1 = UUID.randomUUID();
UUID uuid2 = UUID.randomUUID();
ACI aci1 = ACI.from(UUID.randomUUID());
ACI aci2 = ACI.from(UUID.randomUUID());
recipientIdCache.put(recipient(recipientId1, uuid1, null));
recipientIdCache.put(recipient(recipientId2, uuid2, null));
recipientIdCache.put(recipient(recipientId1, aci1, null));
recipientIdCache.put(recipient(recipientId2, aci2, null));
assertEquals(recipientId1, recipientIdCache.get(uuid1, null));
assertEquals(recipientId2, recipientIdCache.get(uuid2, null));
assertEquals(recipientId1, recipientIdCache.get(aci1, null));
assertEquals(recipientId2, recipientIdCache.get(aci2, null));
}
@Test
public void drops_oldest_when_reaches_cache_limit() {
RecipientId recipientId1 = recipientId();
UUID uuid1 = UUID.randomUUID();
ACI aci1 = ACI.from(UUID.randomUUID());
recipientIdCache.put(recipient(recipientId1, uuid1, null));
recipientIdCache.put(recipient(recipientId1, aci1, null));
for (int i = 0; i < TEST_CACHE_LIMIT; i++) {
recipientIdCache.put(recipient(recipientId(), UUID.randomUUID(), null));
recipientIdCache.put(recipient(recipientId(), ACI.from(UUID.randomUUID()), null));
}
assertNull(recipientIdCache.get(uuid1, null));
assertNull(recipientIdCache.get(aci1, null));
}
@Test
public void remains_in_cache_when_used_before_reaching_cache_limit() {
RecipientId recipientId1 = recipientId();
UUID uuid1 = UUID.randomUUID();
ACI aci1 = ACI.from(UUID.randomUUID());
recipientIdCache.put(recipient(recipientId1, uuid1, null));
recipientIdCache.put(recipient(recipientId1, aci1, null));
for (int i = 0; i < TEST_CACHE_LIMIT - 1; i++) {
recipientIdCache.put(recipient(recipientId(), UUID.randomUUID(), null));
recipientIdCache.put(recipient(recipientId(), ACI.from(UUID.randomUUID()), null));
}
assertEquals(recipientId1, recipientIdCache.get(uuid1, null));
assertEquals(recipientId1, recipientIdCache.get(aci1, null));
recipientIdCache.put(recipient(recipientId(), UUID.randomUUID(), null));
recipientIdCache.put(recipient(recipientId(), ACI.from(UUID.randomUUID()), null));
assertEquals(recipientId1, recipientIdCache.get(uuid1, null));
assertEquals(recipientId1, recipientIdCache.get(aci1, null));
}
private static @NonNull RecipientId recipientId() {
return mock(RecipientId.class);
}
private static @NonNull Recipient recipient(RecipientId recipientId, @Nullable UUID uuid, @Nullable String e164) {
private static @NonNull Recipient recipient(RecipientId recipientId, @Nullable ACI aci, @Nullable String e164) {
Recipient mock = mock(Recipient.class);
when(mock.getId()).thenReturn(recipientId);
when(mock.getUuid()).thenReturn(Optional.fromNullable(uuid));
when(mock.getAci()).thenReturn(Optional.fromNullable(aci));
when(mock.getE164()).thenReturn(Optional.fromNullable(e164));
return mock;

View File

@@ -1,7 +1,5 @@
package org.thoughtcrime.securesms.storage;
import androidx.annotation.NonNull;
import com.annimon.stream.Stream;
import org.junit.Before;
@@ -17,6 +15,7 @@ import org.thoughtcrime.securesms.recipients.Recipient;
import org.thoughtcrime.securesms.storage.StorageSyncHelper.IdDifferenceResult;
import org.thoughtcrime.securesms.util.FeatureFlags;
import org.whispersystems.libsignal.util.guava.Optional;
import org.whispersystems.signalservice.api.push.ACI;
import org.whispersystems.signalservice.api.push.SignalServiceAddress;
import org.whispersystems.signalservice.api.storage.SignalAccountRecord;
import org.whispersystems.signalservice.api.storage.SignalContactRecord;
@@ -25,7 +24,6 @@ import org.whispersystems.signalservice.api.storage.SignalGroupV2Record;
import org.whispersystems.signalservice.api.storage.SignalRecord;
import org.whispersystems.signalservice.api.storage.SignalStorageRecord;
import org.whispersystems.signalservice.api.storage.StorageId;
import org.whispersystems.signalservice.api.util.UuidUtil;
import java.util.Arrays;
import java.util.HashMap;
@@ -33,7 +31,6 @@ import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import static junit.framework.TestCase.assertTrue;
import static org.junit.Assert.assertEquals;
@@ -52,23 +49,15 @@ import static org.thoughtcrime.securesms.testutil.TestHelpers.byteListOf;
@PowerMockRunnerDelegate(JUnit4.class)
public final class StorageSyncHelperTest {
private static final UUID UUID_A = UuidUtil.parseOrThrow("ebef429e-695e-4f51-bcc4-526a60ac68c7");
private static final UUID UUID_B = UuidUtil.parseOrThrow("32119989-77fb-4e18-af70-81d55185c6b1");
private static final UUID UUID_C = UuidUtil.parseOrThrow("b5552203-2bca-44aa-b6f5-9f5d87a335b6");
private static final UUID UUID_D = UuidUtil.parseOrThrow("94829a32-7199-4a7b-8fb4-7e978509ab84");
private static final UUID UUID_SELF = UuidUtil.parseOrThrow("1b2a2ca5-fc9e-4656-8c9f-22cc349ed3af");
private static final ACI ACI_A = ACI.parseOrThrow("ebef429e-695e-4f51-bcc4-526a60ac68c7");
private static final ACI ACI_SELF = ACI.parseOrThrow("1b2a2ca5-fc9e-4656-8c9f-22cc349ed3af");
private static final String E164_A = "+16108675309";
private static final String E164_B = "+16101234567";
private static final String E164_C = "+16101112222";
private static final String E164_D = "+16103334444";
private static final String E164_SELF = "+16105555555";
private static final int UNKNOWN_TYPE = Integer.MAX_VALUE;
private static final Recipient SELF = mock(Recipient.class);
static {
when(SELF.getUuid()).thenReturn(Optional.of(UUID_SELF));
when(SELF.getAci()).thenReturn(Optional.of(ACI_SELF));
when(SELF.getE164()).thenReturn(Optional.of(E164_SELF));
when(SELF.resolve()).thenReturn(SELF);
}
@@ -145,8 +134,8 @@ public final class StorageSyncHelperTest {
byte[] profileKey = new byte[32];
byte[] profileKeyCopy = profileKey.clone();
SignalContactRecord a = contactBuilder(1, UUID_A, E164_A, "a").setProfileKey(profileKey).build();
SignalContactRecord b = contactBuilder(1, UUID_A, E164_A, "a").setProfileKey(profileKeyCopy).build();
SignalContactRecord a = contactBuilder(1, ACI_A, E164_A, "a").setProfileKey(profileKey).build();
SignalContactRecord b = contactBuilder(1, ACI_A, E164_A, "a").setProfileKey(profileKeyCopy).build();
assertEquals(a, b);
assertEquals(a.hashCode(), b.hashCode());
@@ -160,8 +149,8 @@ public final class StorageSyncHelperTest {
byte[] profileKeyCopy = profileKey.clone();
profileKeyCopy[0] = 1;
SignalContactRecord a = contactBuilder(1, UUID_A, E164_A, "a").setProfileKey(profileKey).build();
SignalContactRecord b = contactBuilder(1, UUID_A, E164_A, "a").setProfileKey(profileKeyCopy).build();
SignalContactRecord a = contactBuilder(1, ACI_A, E164_A, "a").setProfileKey(profileKey).build();
SignalContactRecord b = contactBuilder(1, ACI_A, E164_A, "a").setProfileKey(profileKeyCopy).build();
assertNotEquals(a, b);
assertNotEquals(a.hashCode(), b.hashCode());
@@ -169,16 +158,6 @@ public final class StorageSyncHelperTest {
assertTrue(StorageSyncHelper.profileKeyChanged(update(a, b)));
}
private static Set<SignalStorageRecord> recordSetOf(SignalRecord... records) {
LinkedHashSet<SignalStorageRecord> storageRecords = new LinkedHashSet<>();
for (SignalRecord record : records) {
storageRecords.add(record(record));
}
return storageRecords;
}
private static SignalStorageRecord record(SignalRecord record) {
if (record instanceof SignalContactRecord) {
return SignalStorageRecord.forContact(record.getId(), (SignalContactRecord) record);
@@ -194,50 +173,18 @@ public final class StorageSyncHelperTest {
}
private static SignalContactRecord.Builder contactBuilder(int key,
UUID uuid,
ACI aci,
String e164,
String profileName)
{
return new SignalContactRecord.Builder(byteArray(key), new SignalServiceAddress(uuid, e164))
return new SignalContactRecord.Builder(byteArray(key), new SignalServiceAddress(aci, e164))
.setGivenName(profileName);
}
private static SignalContactRecord contact(int key,
UUID uuid,
String e164,
String profileName)
{
return contactBuilder(key, uuid, e164, profileName).build();
}
private static SignalGroupV1Record groupV1(int key,
int groupId,
boolean blocked,
boolean profileSharing)
{
return new SignalGroupV1Record.Builder(byteArray(key), byteArray(groupId, 16)).setBlocked(blocked).setProfileSharingEnabled(profileSharing).build();
}
private static SignalGroupV2Record groupV2(int key,
int groupId,
boolean blocked,
boolean profileSharing)
{
return new SignalGroupV2Record.Builder(byteArray(key), byteArray(groupId, 32)).setBlocked(blocked).setProfileSharingEnabled(profileSharing).build();
}
private static <E extends SignalRecord> StorageRecordUpdate<E> update(E oldRecord, E newRecord) {
return new StorageRecordUpdate<>(oldRecord, newRecord);
}
private static <E extends SignalRecord> StorageRecordUpdate<SignalStorageRecord> recordUpdate(E oldContact, E newContact) {
return new StorageRecordUpdate<>(record(oldContact), record(newContact));
}
private static SignalStorageRecord unknown(int key) {
return SignalStorageRecord.forUnknown(StorageId.forType(byteArray(key), UNKNOWN_TYPE));
}
private static List<StorageId> keyListOf(int... vals) {
return Stream.of(byteListOf(vals)).map(b -> StorageId.forType(b, 1)).toList();
}
@@ -245,35 +192,4 @@ public final class StorageSyncHelperTest {
private static List<StorageId> keyListOf(Map<Integer, Integer> vals) {
return Stream.of(vals).map(e -> StorageId.forType(byteArray(e.getKey()), e.getValue())).toList();
}
private static StorageId contactKey(int val) {
return StorageId.forContact(byteArray(val));
}
private static StorageId groupV1Key(int val) {
return StorageId.forGroupV1(byteArray(val));
}
private static StorageId groupV2Key(int val) {
return StorageId.forGroupV2(byteArray(val));
}
private static StorageId unknownKey(int val) {
return StorageId.forType(byteArray(val), UNKNOWN_TYPE);
}
private static class TestGenerator implements StorageKeyGenerator {
private final int[] keys;
private int index = 0;
private TestGenerator(int... keys) {
this.keys = keys;
}
@Override
public @NonNull byte[] generate() {
return byteArray(keys[index++]);
}
}
}