mirror of
https://github.com/signalapp/Signal-Server
synced 2026-04-20 17:48:04 +01:00
Make adding/removing devices blocking and remove async update plumbing
This commit is contained in:
committed by
Jon Chambers
parent
31de1fc1a3
commit
405b04f07b
@@ -220,7 +220,7 @@ class DeviceControllerTest {
|
||||
final Optional<ApnRegistrationId> apnRegistrationId,
|
||||
final Optional<GcmRegistrationId> gcmRegistrationId,
|
||||
final Optional<String> expectedApnsToken,
|
||||
final Optional<String> expectedGcmToken) {
|
||||
final Optional<String> expectedGcmToken) throws LinkDeviceTokenAlreadyUsedException {
|
||||
|
||||
final Device existingDevice = mock(Device.class);
|
||||
when(existingDevice.getId()).thenReturn(Device.PRIMARY_ID);
|
||||
@@ -249,7 +249,7 @@ class DeviceControllerTest {
|
||||
final Account a = invocation.getArgument(0);
|
||||
final DeviceSpec deviceSpec = invocation.getArgument(1);
|
||||
|
||||
return CompletableFuture.completedFuture(new Pair<>(a, deviceSpec.toDevice(NEXT_DEVICE_ID, testClock, aciIdentityKey)));
|
||||
return new Pair<>(a, deviceSpec.toDevice(NEXT_DEVICE_ID, testClock, aciIdentityKey));
|
||||
});
|
||||
|
||||
when(asyncCommands.set(any(), any(), any())).thenReturn(MockRedisFuture.completedFuture(null));
|
||||
@@ -298,11 +298,12 @@ class DeviceControllerTest {
|
||||
@CartesianTest
|
||||
void deviceDowngrade(@CartesianTest.Enum final DeviceCapability capability,
|
||||
@CartesianTest.Values(booleans = {true, false}) final boolean accountHasCapability,
|
||||
@CartesianTest.Values(booleans = {true, false}) final boolean requestHasCapability) {
|
||||
@CartesianTest.Values(booleans = {true, false}) final boolean requestHasCapability)
|
||||
throws LinkDeviceTokenAlreadyUsedException {
|
||||
|
||||
when(accountsManager.getByAccountIdentifier(AuthHelper.VALID_UUID)).thenReturn(Optional.of(account));
|
||||
when(accountsManager.addDevice(any(), any(), any()))
|
||||
.thenReturn(CompletableFuture.completedFuture(new Pair<>(mock(Account.class), mock(Device.class))));
|
||||
.thenReturn(new Pair<>(mock(Account.class), mock(Device.class)));
|
||||
|
||||
final Device primaryDevice = mock(Device.class);
|
||||
when(primaryDevice.getId()).thenReturn(Device.PRIMARY_ID);
|
||||
@@ -392,7 +393,7 @@ class DeviceControllerTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
void linkDeviceAtomicReusedToken() {
|
||||
void linkDeviceAtomicReusedToken() throws LinkDeviceTokenAlreadyUsedException {
|
||||
final Device existingDevice = mock(Device.class);
|
||||
when(existingDevice.getId()).thenReturn(Device.PRIMARY_ID);
|
||||
when(account.getDevices()).thenReturn(List.of(existingDevice));
|
||||
@@ -416,7 +417,7 @@ class DeviceControllerTest {
|
||||
when(accountsManager.checkDeviceLinkingToken(anyString())).thenReturn(Optional.of(AuthHelper.VALID_UUID));
|
||||
|
||||
when(accountsManager.addDevice(any(), any(), any()))
|
||||
.thenReturn(CompletableFuture.failedFuture(new LinkDeviceTokenAlreadyUsedException()));
|
||||
.thenThrow(new LinkDeviceTokenAlreadyUsedException());
|
||||
|
||||
when(asyncCommands.set(any(), any(), any())).thenReturn(MockRedisFuture.completedFuture(null));
|
||||
|
||||
@@ -729,7 +730,8 @@ class DeviceControllerTest {
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource
|
||||
void linkDeviceRegistrationId(final int registrationId, final int pniRegistrationId, final int expectedStatusCode) {
|
||||
void linkDeviceRegistrationId(final int registrationId, final int pniRegistrationId, final int expectedStatusCode)
|
||||
throws LinkDeviceTokenAlreadyUsedException {
|
||||
final Device existingDevice = mock(Device.class);
|
||||
when(existingDevice.getId()).thenReturn(Device.PRIMARY_ID);
|
||||
when(account.getDevices()).thenReturn(List.of(existingDevice));
|
||||
@@ -750,7 +752,7 @@ class DeviceControllerTest {
|
||||
final Account a = invocation.getArgument(0);
|
||||
final DeviceSpec deviceSpec = invocation.getArgument(1);
|
||||
|
||||
return CompletableFuture.completedFuture(new Pair<>(a, deviceSpec.toDevice(NEXT_DEVICE_ID, testClock, aciIdentityKey)));
|
||||
return new Pair<>(a, deviceSpec.toDevice(NEXT_DEVICE_ID, testClock, aciIdentityKey));
|
||||
});
|
||||
|
||||
when(accountsManager.checkDeviceLinkingToken(anyString())).thenReturn(Optional.of(AuthHelper.VALID_UUID));
|
||||
@@ -835,7 +837,7 @@ class DeviceControllerTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
void maxDevicesTest() {
|
||||
void maxDevicesTest() throws LinkDeviceTokenAlreadyUsedException {
|
||||
final List<Device> devices = IntStream.range(0, DeviceController.MAX_DEVICES + 1)
|
||||
.mapToObj(i -> mock(Device.class))
|
||||
.toList();
|
||||
@@ -891,7 +893,7 @@ class DeviceControllerTest {
|
||||
final byte deviceId = 2;
|
||||
|
||||
when(accountsManager.removeDevice(account, deviceId))
|
||||
.thenReturn(CompletableFuture.completedFuture(account));
|
||||
.thenReturn(account);
|
||||
|
||||
try (final Response response = resources
|
||||
.getJerseyTest()
|
||||
@@ -932,7 +934,7 @@ class DeviceControllerTest {
|
||||
final byte deviceId = 2;
|
||||
|
||||
when(accountsManager.removeDevice(AuthHelper.VALID_ACCOUNT_3, deviceId))
|
||||
.thenReturn(CompletableFuture.completedFuture(account));
|
||||
.thenReturn(account);
|
||||
|
||||
when(accountsManager.getByAccountIdentifier(AuthHelper.VALID_UUID_3))
|
||||
.thenReturn(Optional.of(AuthHelper.VALID_ACCOUNT_3));
|
||||
|
||||
@@ -25,7 +25,6 @@ import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.stream.Stream;
|
||||
import javax.annotation.Nullable;
|
||||
@@ -72,7 +71,7 @@ class DevicesGrpcServiceTest extends SimpleBaseGrpcTest<DevicesGrpcService, Devi
|
||||
.thenReturn(Optional.of(authenticatedAccount));
|
||||
|
||||
when(accountsManager.removeDevice(any(), anyByte()))
|
||||
.thenReturn(CompletableFuture.completedFuture(authenticatedAccount));
|
||||
.thenReturn(authenticatedAccount);
|
||||
|
||||
when(accountsManager.update(any(), any()))
|
||||
.thenAnswer(invocation -> {
|
||||
|
||||
@@ -160,7 +160,6 @@ class AccountsManagerTest {
|
||||
when(asyncClusterCommands.set(any(), any(), any())).thenReturn(MockRedisFuture.completedFuture("OK"));
|
||||
when(asyncClusterCommands.setex(any(), anyLong(), any())).thenReturn(MockRedisFuture.completedFuture("OK"));
|
||||
|
||||
when(accounts.updateTransactionallyAsync(any(), any())).thenReturn(CompletableFuture.completedFuture(null));
|
||||
when(accounts.delete(any(), any())).thenReturn(CompletableFuture.completedFuture(null));
|
||||
|
||||
doAnswer((Answer<Void>) invocation -> {
|
||||
@@ -692,15 +691,13 @@ class AccountsManagerTest {
|
||||
|
||||
Account account = AccountsHelper.generateTestAccount("+14152222222", List.of(primaryDevice, linkedDevice));
|
||||
|
||||
when(accounts.getByAccountIdentifierAsync(account.getUuid()))
|
||||
.thenReturn(CompletableFuture.completedFuture(Optional.of(account)));
|
||||
|
||||
when(accounts.getByAccountIdentifier(account.getUuid())).thenReturn(Optional.of(account));
|
||||
when(keysManager.deleteSingleUsePreKeys(any(), anyByte())).thenReturn(CompletableFuture.completedFuture(null));
|
||||
when(messagesManager.clear(any(), anyByte())).thenReturn(CompletableFuture.completedFuture(null));
|
||||
|
||||
assertTrue(account.getDevice(linkedDevice.getId()).isPresent());
|
||||
|
||||
account = accountsManager.removeDevice(account, linkedDevice.getId()).join();
|
||||
account = accountsManager.removeDevice(account, linkedDevice.getId());
|
||||
|
||||
assertFalse(account.getDevice(linkedDevice.getId()).isPresent());
|
||||
verify(messagesManager, times(2)).clear(account.getUuid(), linkedDevice.getId());
|
||||
@@ -855,7 +852,7 @@ class AccountsManagerTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
void testAddDevice() {
|
||||
void testAddDevice() throws LinkDeviceTokenAlreadyUsedException {
|
||||
final String phoneNumber =
|
||||
PhoneNumberUtil.getInstance().format(PhoneNumberUtil.getInstance().getExampleNumber("US"),
|
||||
PhoneNumberUtil.PhoneNumberFormat.E164);
|
||||
@@ -883,8 +880,7 @@ class AccountsManagerTest {
|
||||
|
||||
when(keysManager.deleteSingleUsePreKeys(any(), anyByte())).thenReturn(CompletableFuture.completedFuture(null));
|
||||
when(messagesManager.clear(any(), anyByte())).thenReturn(CompletableFuture.completedFuture(null));
|
||||
when(accounts.getByAccountIdentifierAsync(aci)).thenReturn(CompletableFuture.completedFuture(Optional.of(account)));
|
||||
when(accounts.updateTransactionallyAsync(any(), any())).thenReturn(CompletableFuture.completedFuture(null));
|
||||
when(accounts.getByAccountIdentifier(aci)).thenReturn(Optional.of(account));
|
||||
|
||||
CLOCK.pin(CLOCK.instant().plusSeconds(60));
|
||||
|
||||
@@ -902,8 +898,7 @@ class AccountsManagerTest {
|
||||
pniSignedPreKey,
|
||||
aciPqLastResortPreKey,
|
||||
pniPqLastResortPreKey),
|
||||
accountsManager.generateLinkDeviceToken(aci))
|
||||
.join();
|
||||
accountsManager.generateLinkDeviceToken(aci));
|
||||
|
||||
verify(keysManager).deleteSingleUsePreKeys(aci, nextDeviceId);
|
||||
verify(keysManager).deleteSingleUsePreKeys(pni, nextDeviceId);
|
||||
|
||||
@@ -40,7 +40,6 @@ import java.util.Optional;
|
||||
import java.util.Random;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.CompletionException;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.function.BiConsumer;
|
||||
@@ -648,7 +647,7 @@ class AccountsTest {
|
||||
|
||||
account.getPrimaryDevice().setName(deviceName);
|
||||
|
||||
accounts.updateTransactionallyAsync(account, List.of(TransactWriteItem.builder()
|
||||
accounts.updateTransactionally(account, List.of(TransactWriteItem.builder()
|
||||
.put(Put.builder()
|
||||
.tableName(Tables.CLIENT_RELEASES.tableName())
|
||||
.item(Map.of(
|
||||
@@ -656,7 +655,7 @@ class AccountsTest {
|
||||
ClientReleases.ATTR_VERSION, AttributeValues.fromString("test")
|
||||
))
|
||||
.build())
|
||||
.build())).toCompletableFuture().join();
|
||||
.build()));
|
||||
|
||||
assertArrayEquals(deviceName,
|
||||
accounts.getByAccountIdentifier(account.getUuid()).orElseThrow().getPrimaryDevice().getName());
|
||||
@@ -678,8 +677,8 @@ class AccountsTest {
|
||||
|
||||
account.setVersion(account.getVersion() - 1);
|
||||
|
||||
final CompletionException completionException = assertThrows(CompletionException.class,
|
||||
() -> accounts.updateTransactionallyAsync(account, List.of(TransactWriteItem.builder()
|
||||
assertThrows(ContestedOptimisticLockException.class,
|
||||
() -> accounts.updateTransactionally(account, List.of(TransactWriteItem.builder()
|
||||
.put(Put.builder()
|
||||
.tableName(Tables.CLIENT_RELEASES.tableName())
|
||||
.item(Map.of(
|
||||
@@ -687,19 +686,17 @@ class AccountsTest {
|
||||
ClientReleases.ATTR_VERSION, AttributeValues.fromString("test")
|
||||
))
|
||||
.build())
|
||||
.build())).toCompletableFuture().join());
|
||||
|
||||
assertInstanceOf(ContestedOptimisticLockException.class, completionException.getCause());
|
||||
.build())));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testUpdateTransactionallyWithMockTransactionConflictException() {
|
||||
final DynamoDbAsyncClient dynamoDbAsyncClient = mock(DynamoDbAsyncClient.class);
|
||||
final DynamoDbClient dynamoDbClient = mock(DynamoDbClient.class);
|
||||
|
||||
accounts = new Accounts(
|
||||
clock,
|
||||
mock(DynamoDbClient.class),
|
||||
dynamoDbAsyncClient,
|
||||
dynamoDbClient,
|
||||
mock(DynamoDbAsyncClient.class),
|
||||
Tables.ACCOUNTS.tableName(),
|
||||
Tables.NUMBERS.tableName(),
|
||||
Tables.PNI_ASSIGNMENTS.tableName(),
|
||||
@@ -707,18 +704,17 @@ class AccountsTest {
|
||||
Tables.DELETED_ACCOUNTS.tableName(),
|
||||
Tables.USED_LINK_DEVICE_TOKENS.tableName());
|
||||
|
||||
when(dynamoDbAsyncClient.transactWriteItems(any(TransactWriteItemsRequest.class)))
|
||||
.thenReturn(CompletableFuture.failedFuture(TransactionCanceledException.builder()
|
||||
when(dynamoDbClient.transactWriteItems(any(TransactWriteItemsRequest.class)))
|
||||
.thenThrow(TransactionCanceledException.builder()
|
||||
.cancellationReasons(CancellationReason.builder()
|
||||
.code("TransactionConflict")
|
||||
.build())
|
||||
.build()));
|
||||
.build());
|
||||
|
||||
Account account = generateAccount("+14151112222", UUID.randomUUID(), UUID.randomUUID());
|
||||
final Account account = generateAccount("+14151112222", UUID.randomUUID(), UUID.randomUUID());
|
||||
|
||||
assertThatThrownBy(() -> accounts.updateTransactionallyAsync(account, Collections.emptyList()).toCompletableFuture().join())
|
||||
.isInstanceOfAny(CompletionException.class)
|
||||
.hasCauseInstanceOf(ContestedOptimisticLockException.class);
|
||||
assertThatThrownBy(() -> accounts.updateTransactionally(account, Collections.emptyList()))
|
||||
.isInstanceOfAny(ContestedOptimisticLockException.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -2,7 +2,6 @@ package org.whispersystems.textsecuregcm.storage;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.junit.jupiter.api.Assertions.assertInstanceOf;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
@@ -21,7 +20,6 @@ import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.CompletionException;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
@@ -174,7 +172,7 @@ public class AddRemoveDeviceIntegrationTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
void addDevice() throws InterruptedException {
|
||||
void addDevice() throws InterruptedException, LinkDeviceTokenAlreadyUsedException {
|
||||
final String number = PhoneNumberUtil.getInstance().format(
|
||||
PhoneNumberUtil.getInstance().getExampleNumber("US"),
|
||||
PhoneNumberUtil.PhoneNumberFormat.E164);
|
||||
@@ -200,8 +198,7 @@ public class AddRemoveDeviceIntegrationTest {
|
||||
KeysHelper.signedECPreKey(2, pniKeyPair),
|
||||
KeysHelper.signedKEMPreKey(3, aciKeyPair),
|
||||
KeysHelper.signedKEMPreKey(4, pniKeyPair)),
|
||||
accountsManager.generateLinkDeviceToken(account.getIdentifier(IdentityType.ACI)))
|
||||
.join();
|
||||
accountsManager.generateLinkDeviceToken(account.getIdentifier(IdentityType.ACI)));
|
||||
|
||||
assertEquals(2, updatedAccountAndDevice.first().getDevices().size());
|
||||
|
||||
@@ -223,7 +220,7 @@ public class AddRemoveDeviceIntegrationTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
void addDeviceReusedToken() throws InterruptedException {
|
||||
void addDeviceReusedToken() throws InterruptedException, LinkDeviceTokenAlreadyUsedException {
|
||||
final String number = PhoneNumberUtil.getInstance().format(
|
||||
PhoneNumberUtil.getInstance().getExampleNumber("US"),
|
||||
PhoneNumberUtil.PhoneNumberFormat.E164);
|
||||
@@ -251,14 +248,13 @@ public class AddRemoveDeviceIntegrationTest {
|
||||
KeysHelper.signedECPreKey(2, pniKeyPair),
|
||||
KeysHelper.signedKEMPreKey(3, aciKeyPair),
|
||||
KeysHelper.signedKEMPreKey(4, pniKeyPair)),
|
||||
linkDeviceToken)
|
||||
.join();
|
||||
linkDeviceToken);
|
||||
|
||||
assertEquals(2,
|
||||
accountsManager.getByAccountIdentifier(updatedAccountAndDevice.first().getUuid()).orElseThrow().getDevices()
|
||||
.size());
|
||||
|
||||
final CompletionException completionException = assertThrows(CompletionException.class,
|
||||
assertThrows(LinkDeviceTokenAlreadyUsedException.class,
|
||||
() -> accountsManager.addDevice(account, new DeviceSpec(
|
||||
"device-name".getBytes(StandardCharsets.UTF_8),
|
||||
"password",
|
||||
@@ -273,10 +269,7 @@ public class AddRemoveDeviceIntegrationTest {
|
||||
KeysHelper.signedECPreKey(2, pniKeyPair),
|
||||
KeysHelper.signedKEMPreKey(3, aciKeyPair),
|
||||
KeysHelper.signedKEMPreKey(4, pniKeyPair)),
|
||||
linkDeviceToken)
|
||||
.join());
|
||||
|
||||
assertInstanceOf(LinkDeviceTokenAlreadyUsedException.class, completionException.getCause());
|
||||
linkDeviceToken));
|
||||
|
||||
assertEquals(2,
|
||||
accountsManager.getByAccountIdentifier(updatedAccountAndDevice.first().getUuid()).orElseThrow().getDevices()
|
||||
@@ -284,7 +277,7 @@ public class AddRemoveDeviceIntegrationTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
void removeDevice() throws InterruptedException {
|
||||
void removeDevice() throws InterruptedException, LinkDeviceTokenAlreadyUsedException {
|
||||
final String number = PhoneNumberUtil.getInstance().format(
|
||||
PhoneNumberUtil.getInstance().getExampleNumber("US"),
|
||||
PhoneNumberUtil.PhoneNumberFormat.E164);
|
||||
@@ -310,12 +303,11 @@ public class AddRemoveDeviceIntegrationTest {
|
||||
KeysHelper.signedECPreKey(2, pniKeyPair),
|
||||
KeysHelper.signedKEMPreKey(3, aciKeyPair),
|
||||
KeysHelper.signedKEMPreKey(4, pniKeyPair)),
|
||||
accountsManager.generateLinkDeviceToken(account.getIdentifier(IdentityType.ACI)))
|
||||
.join();
|
||||
accountsManager.generateLinkDeviceToken(account.getIdentifier(IdentityType.ACI)));
|
||||
|
||||
final byte addedDeviceId = updatedAccountAndDevice.second().getId();
|
||||
|
||||
final Account updatedAccount = accountsManager.removeDevice(updatedAccountAndDevice.first(), addedDeviceId).join();
|
||||
final Account updatedAccount = accountsManager.removeDevice(updatedAccountAndDevice.first(), addedDeviceId);
|
||||
|
||||
assertEquals(1, updatedAccount.getDevices().size());
|
||||
|
||||
@@ -334,7 +326,7 @@ public class AddRemoveDeviceIntegrationTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
void removeDevicePartialFailure() throws InterruptedException {
|
||||
void removeDevicePartialFailure() throws InterruptedException, LinkDeviceTokenAlreadyUsedException {
|
||||
final String number = PhoneNumberUtil.getInstance().format(
|
||||
PhoneNumberUtil.getInstance().getExampleNumber("US"),
|
||||
PhoneNumberUtil.PhoneNumberFormat.E164);
|
||||
@@ -362,16 +354,15 @@ public class AddRemoveDeviceIntegrationTest {
|
||||
KeysHelper.signedECPreKey(2, pniKeyPair),
|
||||
KeysHelper.signedKEMPreKey(3, aciKeyPair),
|
||||
KeysHelper.signedKEMPreKey(4, pniKeyPair)),
|
||||
accountsManager.generateLinkDeviceToken(account.getIdentifier(IdentityType.ACI)))
|
||||
.join();
|
||||
accountsManager.generateLinkDeviceToken(account.getIdentifier(IdentityType.ACI)));
|
||||
|
||||
final byte addedDeviceId = updatedAccountAndDevice.second().getId();
|
||||
|
||||
when(messagesManager.clear(any(), anyByte()))
|
||||
.thenReturn(CompletableFuture.failedFuture(new RuntimeException("OH NO")));
|
||||
|
||||
assertThrows(CompletionException.class,
|
||||
() -> accountsManager.removeDevice(updatedAccountAndDevice.first(), addedDeviceId).join());
|
||||
assertThrows(RuntimeException.class,
|
||||
() -> accountsManager.removeDevice(updatedAccountAndDevice.first(), addedDeviceId));
|
||||
|
||||
final Account retrievedAccount = accountsManager.getByAccountIdentifierAsync(aci).join().orElseThrow();
|
||||
|
||||
@@ -393,7 +384,7 @@ public class AddRemoveDeviceIntegrationTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
void waitForNewLinkedDevice() throws InterruptedException {
|
||||
void waitForNewLinkedDevice() throws InterruptedException, LinkDeviceTokenAlreadyUsedException {
|
||||
final String number = PhoneNumberUtil.getInstance().format(
|
||||
PhoneNumberUtil.getInstance().getExampleNumber("US"),
|
||||
PhoneNumberUtil.PhoneNumberFormat.E164);
|
||||
@@ -433,8 +424,7 @@ public class AddRemoveDeviceIntegrationTest {
|
||||
KeysHelper.signedECPreKey(2, pniKeyPair),
|
||||
KeysHelper.signedKEMPreKey(3, aciKeyPair),
|
||||
KeysHelper.signedKEMPreKey(4, pniKeyPair)),
|
||||
linkDeviceToken)
|
||||
.join();
|
||||
linkDeviceToken);
|
||||
|
||||
final Optional<DeviceInfo> maybeDeviceInfo = activeFuture.join();
|
||||
|
||||
@@ -447,7 +437,7 @@ public class AddRemoveDeviceIntegrationTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
void waitForNewLinkedDeviceAlreadyAdded() throws InterruptedException {
|
||||
void waitForNewLinkedDeviceAlreadyAdded() throws InterruptedException, LinkDeviceTokenAlreadyUsedException {
|
||||
final String number = PhoneNumberUtil.getInstance().format(
|
||||
PhoneNumberUtil.getInstance().getExampleNumber("US"),
|
||||
PhoneNumberUtil.PhoneNumberFormat.E164);
|
||||
@@ -475,8 +465,7 @@ public class AddRemoveDeviceIntegrationTest {
|
||||
KeysHelper.signedECPreKey(2, pniKeyPair),
|
||||
KeysHelper.signedKEMPreKey(3, aciKeyPair),
|
||||
KeysHelper.signedKEMPreKey(4, pniKeyPair)),
|
||||
linkDeviceToken)
|
||||
.join();
|
||||
linkDeviceToken);
|
||||
|
||||
when(messagesManager.getEarliestUndeliveredTimestampForDevice(account.getUuid(), account.getPrimaryDevice()))
|
||||
.thenReturn(CompletableFuture.completedFuture(Optional.empty()));
|
||||
@@ -520,7 +509,7 @@ public class AddRemoveDeviceIntegrationTest {
|
||||
"10_000,10_001,false", // pending message after now
|
||||
})
|
||||
void waitForMessageFetch(long currentTime, Long oldestMessage, boolean shouldWait)
|
||||
throws InterruptedException {
|
||||
throws InterruptedException, LinkDeviceTokenAlreadyUsedException {
|
||||
final String number = PhoneNumberUtil.getInstance().format(
|
||||
PhoneNumberUtil.getInstance().getExampleNumber("US"),
|
||||
PhoneNumberUtil.PhoneNumberFormat.E164);
|
||||
@@ -531,23 +520,21 @@ public class AddRemoveDeviceIntegrationTest {
|
||||
final String linkDeviceToken = accountsManager.generateLinkDeviceToken(UUID.randomUUID());
|
||||
final String linkDeviceTokenIdentifier = AccountsManager.getLinkDeviceTokenIdentifier(linkDeviceToken);
|
||||
|
||||
final Pair<Account, Device> updatedAccountAndDevice =
|
||||
accountsManager.addDevice(account, new DeviceSpec(
|
||||
"device-name".getBytes(StandardCharsets.UTF_8),
|
||||
"password",
|
||||
"OWT",
|
||||
Set.of(),
|
||||
1,
|
||||
2,
|
||||
true,
|
||||
Optional.empty(),
|
||||
Optional.empty(),
|
||||
KeysHelper.signedECPreKey(1, aciKeyPair),
|
||||
KeysHelper.signedECPreKey(2, pniKeyPair),
|
||||
KeysHelper.signedKEMPreKey(3, aciKeyPair),
|
||||
KeysHelper.signedKEMPreKey(4, pniKeyPair)),
|
||||
linkDeviceToken)
|
||||
.join();
|
||||
accountsManager.addDevice(account, new DeviceSpec(
|
||||
"device-name".getBytes(StandardCharsets.UTF_8),
|
||||
"password",
|
||||
"OWT",
|
||||
Set.of(),
|
||||
1,
|
||||
2,
|
||||
true,
|
||||
Optional.empty(),
|
||||
Optional.empty(),
|
||||
KeysHelper.signedECPreKey(1, aciKeyPair),
|
||||
KeysHelper.signedECPreKey(2, pniKeyPair),
|
||||
KeysHelper.signedKEMPreKey(3, aciKeyPair),
|
||||
KeysHelper.signedKEMPreKey(4, pniKeyPair)),
|
||||
linkDeviceToken);
|
||||
|
||||
when(messagesManager.getEarliestUndeliveredTimestampForDevice(account.getUuid(), account.getPrimaryDevice()))
|
||||
.thenReturn(CompletableFuture.completedFuture(Optional.ofNullable(oldestMessage).map(Instant::ofEpochMilli)));
|
||||
@@ -564,7 +551,7 @@ public class AddRemoveDeviceIntegrationTest {
|
||||
@Timeout(value = 10, threadMode = Timeout.ThreadMode.SEPARATE_THREAD)
|
||||
@Test
|
||||
void waitForMessageFetchRetries()
|
||||
throws InterruptedException {
|
||||
throws InterruptedException, LinkDeviceTokenAlreadyUsedException {
|
||||
final String number = PhoneNumberUtil.getInstance().format(
|
||||
PhoneNumberUtil.getInstance().getExampleNumber("US"),
|
||||
PhoneNumberUtil.PhoneNumberFormat.E164);
|
||||
@@ -577,21 +564,20 @@ public class AddRemoveDeviceIntegrationTest {
|
||||
|
||||
clock.pin(Instant.ofEpochMilli(0));
|
||||
accountsManager.addDevice(account, new DeviceSpec(
|
||||
"device-name".getBytes(StandardCharsets.UTF_8),
|
||||
"password",
|
||||
"OWT",
|
||||
Set.of(),
|
||||
1,
|
||||
2,
|
||||
true,
|
||||
Optional.empty(),
|
||||
Optional.empty(),
|
||||
KeysHelper.signedECPreKey(1, aciKeyPair),
|
||||
KeysHelper.signedECPreKey(2, pniKeyPair),
|
||||
KeysHelper.signedKEMPreKey(3, aciKeyPair),
|
||||
KeysHelper.signedKEMPreKey(4, pniKeyPair)),
|
||||
linkDeviceToken)
|
||||
.join();
|
||||
"device-name".getBytes(StandardCharsets.UTF_8),
|
||||
"password",
|
||||
"OWT",
|
||||
Set.of(),
|
||||
1,
|
||||
2,
|
||||
true,
|
||||
Optional.empty(),
|
||||
Optional.empty(),
|
||||
KeysHelper.signedECPreKey(1, aciKeyPair),
|
||||
KeysHelper.signedECPreKey(2, pniKeyPair),
|
||||
KeysHelper.signedKEMPreKey(3, aciKeyPair),
|
||||
KeysHelper.signedKEMPreKey(4, pniKeyPair)),
|
||||
linkDeviceToken);
|
||||
|
||||
when(messagesManager.getEarliestUndeliveredTimestampForDevice(account.getUuid(), account.getPrimaryDevice()))
|
||||
// Has a message older than the message epoch
|
||||
|
||||
@@ -34,13 +34,11 @@ import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.CompletionException;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.ThreadLocalRandom;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
import java.util.stream.Stream;
|
||||
import org.apache.commons.lang3.RandomStringUtils;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
@@ -100,7 +98,7 @@ class MessagePersisterTest {
|
||||
|
||||
when(accountsManager.getByAccountIdentifier(DESTINATION_ACCOUNT_UUID)).thenReturn(Optional.of(destinationAccount));
|
||||
when(accountsManager.removeDevice(any(), anyByte()))
|
||||
.thenAnswer(invocation -> CompletableFuture.completedFuture(invocation.getArgument(0)));
|
||||
.thenAnswer(invocation -> invocation.getArgument(0));
|
||||
|
||||
when(destinationAccount.getUuid()).thenReturn(DESTINATION_ACCOUNT_UUID);
|
||||
when(destinationAccount.getIdentifier(IdentityType.ACI)).thenReturn(DESTINATION_ACCOUNT_UUID);
|
||||
@@ -399,9 +397,9 @@ class MessagePersisterTest {
|
||||
when(destinationAccount.getDevices()).thenReturn(List.of(primary, activeA, inactiveB, inactiveC, activeD, destination));
|
||||
|
||||
when(messagesManager.persistMessages(any(UUID.class), any(), anyList())).thenThrow(ItemCollectionSizeLimitExceededException.builder().build());
|
||||
when(accountsManager.removeDevice(destinationAccount, DESTINATION_DEVICE_ID)).thenReturn(CompletableFuture.failedFuture(new TimeoutException()));
|
||||
when(accountsManager.removeDevice(destinationAccount, DESTINATION_DEVICE_ID)).thenThrow(new RuntimeException());
|
||||
|
||||
assertThrows(CompletionException.class, () -> messagePersister.persistQueue(destinationAccount, DESTINATION_DEVICE, "test"));
|
||||
assertThrows(RuntimeException.class, () -> messagePersister.persistQueue(destinationAccount, DESTINATION_DEVICE, "test"));
|
||||
}
|
||||
|
||||
@SuppressWarnings("SameParameterValue")
|
||||
|
||||
@@ -19,7 +19,6 @@ import java.time.ZoneId;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import net.sourceforge.argparse4j.inf.Namespace;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.ValueSource;
|
||||
@@ -70,7 +69,7 @@ class UnlinkDevicesWithIdlePrimaryCommandTest {
|
||||
void crawlAccounts(final boolean isDryRun) {
|
||||
final AccountsManager accountsManager = mock(AccountsManager.class);
|
||||
when(accountsManager.removeDevice(any(), anyByte()))
|
||||
.thenReturn(CompletableFuture.completedFuture(null));
|
||||
.thenReturn(null);
|
||||
|
||||
final Duration idleDeviceLastSeenDuration =
|
||||
Duration.ofDays(UnlinkDevicesWithIdlePrimaryCommand.DEFAULT_PRIMARY_IDLE_DAYS).plus(Duration.ofDays(1));
|
||||
|
||||
Reference in New Issue
Block a user