Add PNI support to AccountLockManager

This commit is contained in:
Chris Eager
2024-11-22 10:11:27 -06:00
committed by Chris Eager
parent 73812b06be
commit eb55b80bdc
7 changed files with 92 additions and 58 deletions

View File

@@ -12,6 +12,7 @@ import com.amazonaws.services.dynamodbv2.ReleaseLockOptions;
import com.google.i18n.phonenumbers.PhoneNumberUtil;
import java.util.Collections;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
@@ -33,6 +34,9 @@ class AccountLockManagerTest {
private static final String SECOND_NUMBER = PhoneNumberUtil.getInstance().format(
PhoneNumberUtil.getInstance().getExampleNumber("JP"), PhoneNumberUtil.PhoneNumberFormat.E164);
private static final UUID FIRST_PNI = UUID.randomUUID();
private static final UUID SECOND_PNI = UUID.randomUUID();
@BeforeEach
void setUp() {
lockClient = mock(AmazonDynamoDBLockClient.class);
@@ -51,47 +55,53 @@ class AccountLockManagerTest {
@Test
void withLock() throws InterruptedException {
accountLockManager.withLock(List.of(FIRST_NUMBER, SECOND_NUMBER), () -> {}, executor);
accountLockManager.withLock(List.of(FIRST_NUMBER, SECOND_NUMBER), List.of(FIRST_PNI, SECOND_PNI), () -> {
}, executor);
verify(lockClient, times(2)).acquireLock(any());
verify(lockClient, times(2)).releaseLock(any(ReleaseLockOptions.class));
verify(lockClient, times(4)).acquireLock(any());
verify(lockClient, times(4)).releaseLock(any(ReleaseLockOptions.class));
}
@Test
void withLockTaskThrowsException() throws InterruptedException {
assertThrows(RuntimeException.class, () -> accountLockManager.withLock(List.of(FIRST_NUMBER, SECOND_NUMBER), () -> {
assertThrows(RuntimeException.class,
() -> accountLockManager.withLock(List.of(FIRST_NUMBER, SECOND_NUMBER), List.of(FIRST_PNI, SECOND_PNI), () -> {
throw new RuntimeException();
}, executor));
verify(lockClient, times(2)).acquireLock(any());
verify(lockClient, times(2)).releaseLock(any(ReleaseLockOptions.class));
verify(lockClient, times(4)).acquireLock(any());
verify(lockClient, times(4)).releaseLock(any(ReleaseLockOptions.class));
}
@Test
void withLockEmptyList() {
final Runnable task = mock(Runnable.class);
assertThrows(IllegalArgumentException.class, () -> accountLockManager.withLock(Collections.emptyList(), () -> {}, executor));
assertThrows(IllegalArgumentException.class,
() -> accountLockManager.withLock(Collections.emptyList(), Collections.emptyList(), () -> {
},
executor));
verify(task, never()).run();
}
@Test
void withLockAsync() throws InterruptedException {
accountLockManager.withLockAsync(List.of(FIRST_NUMBER, SECOND_NUMBER),
() -> CompletableFuture.completedFuture(null), executor).join();
List.of(FIRST_PNI, SECOND_PNI), () -> CompletableFuture.completedFuture(null), executor).join();
verify(lockClient, times(2)).acquireLock(any());
verify(lockClient, times(2)).releaseLock(any(ReleaseLockOptions.class));
verify(lockClient, times(4)).acquireLock(any());
verify(lockClient, times(4)).releaseLock(any(ReleaseLockOptions.class));
}
@Test
void withLockAsyncTaskThrowsException() throws InterruptedException {
assertThrows(RuntimeException.class,
() -> accountLockManager.withLockAsync(List.of(FIRST_NUMBER, SECOND_NUMBER),
() -> CompletableFuture.failedFuture(new RuntimeException()), executor).join());
List.of(FIRST_PNI, SECOND_PNI), () -> CompletableFuture.failedFuture(new RuntimeException()), executor)
.join());
verify(lockClient, times(2)).acquireLock(any());
verify(lockClient, times(2)).releaseLock(any(ReleaseLockOptions.class));
verify(lockClient, times(4)).acquireLock(any());
verify(lockClient, times(4)).releaseLock(any(ReleaseLockOptions.class));
}
@Test
@@ -100,7 +110,7 @@ class AccountLockManagerTest {
assertThrows(IllegalArgumentException.class,
() -> accountLockManager.withLockAsync(Collections.emptyList(),
() -> CompletableFuture.completedFuture(null), executor));
Collections.emptyList(), () -> CompletableFuture.completedFuture(null), executor));
verify(task, never()).run();
}

View File

@@ -10,6 +10,7 @@ import static org.junit.jupiter.api.Assertions.assertArrayEquals;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyList;
import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.atLeast;
@@ -50,7 +51,6 @@ import org.whispersystems.textsecuregcm.auth.UnidentifiedAccessUtil;
import org.whispersystems.textsecuregcm.configuration.dynamic.DynamicConfiguration;
import org.whispersystems.textsecuregcm.entities.AccountAttributes;
import org.whispersystems.textsecuregcm.identity.IdentityType;
import org.whispersystems.textsecuregcm.push.WebSocketConnectionEventManager;
import org.whispersystems.textsecuregcm.redis.FaultTolerantRedisClient;
import org.whispersystems.textsecuregcm.securestorage.SecureStorageClient;
import org.whispersystems.textsecuregcm.securevaluerecovery.SecureValueRecovery2Client;
@@ -107,14 +107,14 @@ class AccountsManagerConcurrentModificationIntegrationTest {
final AccountLockManager accountLockManager = mock(AccountLockManager.class);
doAnswer(invocation -> {
final Runnable task = invocation.getArgument(1);
final Runnable task = invocation.getArgument(2);
task.run();
return null;
}).when(accountLockManager).withLock(any(), any(), any());
}).when(accountLockManager).withLock(any(), anyList(), any(), any());
when(accountLockManager.withLockAsync(any(), any(), any())).thenAnswer(invocation -> {
final Supplier<CompletableFuture<?>> taskSupplier = invocation.getArgument(1);
when(accountLockManager.withLockAsync(any(), anyList(), any(), any())).thenAnswer(invocation -> {
final Supplier<CompletableFuture<?>> taskSupplier = invocation.getArgument(2);
taskSupplier.get().join();
return CompletableFuture.completedFuture(null);

View File

@@ -15,6 +15,7 @@ import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyByte;
import static org.mockito.ArgumentMatchers.anyList;
import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.ArgumentMatchers.argThat;
import static org.mockito.ArgumentMatchers.eq;
@@ -208,14 +209,14 @@ class AccountsManagerTest {
final AccountLockManager accountLockManager = mock(AccountLockManager.class);
doAnswer(invocation -> {
final Runnable task = invocation.getArgument(1);
final Runnable task = invocation.getArgument(2);
task.run();
return null;
}).when(accountLockManager).withLock(any(), any(), any());
}).when(accountLockManager).withLock(any(), anyList(), any(), any());
when(accountLockManager.withLockAsync(any(), any(), any())).thenAnswer(invocation -> {
final Supplier<CompletableFuture<?>> taskSupplier = invocation.getArgument(1);
when(accountLockManager.withLockAsync(any(), anyList(), any(), any())).thenAnswer(invocation -> {
final Supplier<CompletableFuture<?>> taskSupplier = invocation.getArgument(2);
return taskSupplier.get();
});

View File

@@ -10,6 +10,7 @@ import static org.junit.jupiter.api.Assertions.assertArrayEquals;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyList;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
@@ -113,14 +114,14 @@ class AccountsManagerUsernameIntegrationTest {
final AccountLockManager accountLockManager = mock(AccountLockManager.class);
doAnswer(invocation -> {
final Runnable task = invocation.getArgument(1);
final Runnable task = invocation.getArgument(2);
task.run();
return null;
}).when(accountLockManager).withLock(any(), any(), any());
}).when(accountLockManager).withLock(any(), anyList(), any(), any());
when(accountLockManager.withLockAsync(any(), any(), any())).thenAnswer(invocation -> {
final Supplier<CompletableFuture<?>> taskSupplier = invocation.getArgument(1);
when(accountLockManager.withLockAsync(any(), anyList(), any(), any())).thenAnswer(invocation -> {
final Supplier<CompletableFuture<?>> taskSupplier = invocation.getArgument(2);
taskSupplier.get().join();
return CompletableFuture.completedFuture(null);