Add test for round-trip AccountsManager JSON serialization
This commit is contained in:
parent
708f23a2ee
commit
f181397664
|
@ -915,7 +915,7 @@ public class AccountsManager {
|
|||
|
||||
private void redisSet(Account account) {
|
||||
try (Timer.Context ignored = redisSetTimer.time()) {
|
||||
final String accountJson = ACCOUNT_REDIS_JSON_WRITER.writeValueAsString(account);
|
||||
final String accountJson = writeRedisAccountJson(account);
|
||||
|
||||
cacheCluster.useCluster(connection -> {
|
||||
final RedisAdvancedClusterCommands<String, String> commands = connection.sync();
|
||||
|
@ -936,7 +936,7 @@ public class AccountsManager {
|
|||
final String accountJson;
|
||||
|
||||
try {
|
||||
accountJson = ACCOUNT_REDIS_JSON_WRITER.writeValueAsString(account);
|
||||
accountJson = writeRedisAccountJson(account);
|
||||
} catch (final JsonProcessingException e) {
|
||||
throw new UncheckedIOException(e);
|
||||
}
|
||||
|
@ -1047,7 +1047,8 @@ public class AccountsManager {
|
|||
.toCompletableFuture();
|
||||
}
|
||||
|
||||
private static Optional<Account> parseAccountJson(@Nullable final String accountJson, final UUID uuid) {
|
||||
@VisibleForTesting
|
||||
static Optional<Account> parseAccountJson(@Nullable final String accountJson, final UUID uuid) {
|
||||
try {
|
||||
if (StringUtils.isNotBlank(accountJson)) {
|
||||
Account account = SystemMapper.jsonMapper().readValue(accountJson, Account.class);
|
||||
|
@ -1067,6 +1068,11 @@ public class AccountsManager {
|
|||
}
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
static String writeRedisAccountJson(final Account account) throws JsonProcessingException {
|
||||
return ACCOUNT_REDIS_JSON_WRITER.writeValueAsString(account);
|
||||
}
|
||||
|
||||
private void redisDelete(final Account account) {
|
||||
try (final Timer.Context ignored = redisDeleteTimer.time()) {
|
||||
cacheCluster.useCluster(connection -> {
|
||||
|
|
|
@ -31,6 +31,8 @@ import static org.mockito.Mockito.when;
|
|||
import io.lettuce.core.RedisException;
|
||||
import io.lettuce.core.cluster.api.async.RedisAdvancedClusterAsyncCommands;
|
||||
import io.lettuce.core.cluster.api.sync.RedisAdvancedClusterCommands;
|
||||
import java.io.InputStream;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.time.Clock;
|
||||
import java.time.Duration;
|
||||
import java.util.ArrayList;
|
||||
|
@ -39,6 +41,7 @@ import java.util.Collections;
|
|||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
@ -1328,6 +1331,46 @@ class AccountsManagerTest {
|
|||
assertThrows(AssertionError.class, () -> accountsManager.update(account, a -> a.setUsernameHash(USERNAME_HASH_1)));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testJsonRoundTripSerialization() throws Exception {
|
||||
String originalJson;
|
||||
try (InputStream inputStream = getClass().getResourceAsStream(
|
||||
"AccountsManagerTest-testJsonRoundTripSerialization.json")) {
|
||||
Objects.requireNonNull(inputStream);
|
||||
originalJson = new String(inputStream.readAllBytes(), StandardCharsets.UTF_8);
|
||||
}
|
||||
|
||||
final Account originalAccount = AccountsManager.parseAccountJson(originalJson,
|
||||
UUID.fromString("111111-1111-1111-1111-111111111111")).orElseThrow();
|
||||
|
||||
final String serialized = AccountsManager.writeRedisAccountJson(originalAccount);
|
||||
final Account parsedAccount = AccountsManager.parseAccountJson(serialized, originalAccount.getUuid()).orElseThrow();
|
||||
|
||||
assertEquals(originalAccount.getUuid(), parsedAccount.getUuid());
|
||||
assertEquals(originalAccount.getPhoneNumberIdentifier(), parsedAccount.getPhoneNumberIdentifier());
|
||||
assertEquals(originalAccount.getIdentityKey(IdentityType.ACI), parsedAccount.getIdentityKey(IdentityType.ACI));
|
||||
assertEquals(originalAccount.getIdentityKey(IdentityType.PNI), parsedAccount.getIdentityKey(IdentityType.PNI));
|
||||
assertEquals(originalAccount.getNumber(), parsedAccount.getNumber());
|
||||
assertArrayEquals(originalAccount.getUnidentifiedAccessKey().orElseThrow(),
|
||||
parsedAccount.getUnidentifiedAccessKey().orElseThrow());
|
||||
assertEquals(originalAccount.isDiscoverableByPhoneNumber(), parsedAccount.isDiscoverableByPhoneNumber());
|
||||
assertEquals(originalAccount.isUnrestrictedUnidentifiedAccess(), parsedAccount.isUnrestrictedUnidentifiedAccess());
|
||||
|
||||
assertEquals(originalAccount.getDevices().size(), parsedAccount.getDevices().size());
|
||||
|
||||
final Device originalDevice = originalAccount.getMasterDevice().orElseThrow();
|
||||
final Device parsedDevice = parsedAccount.getMasterDevice().orElseThrow();
|
||||
|
||||
assertEquals(originalDevice.getId(), parsedDevice.getId());
|
||||
assertEquals(originalDevice.getSignedPreKey(IdentityType.ACI), parsedDevice.getSignedPreKey(IdentityType.ACI));
|
||||
assertEquals(originalDevice.getSignedPreKey(IdentityType.PNI), parsedDevice.getSignedPreKey(IdentityType.PNI));
|
||||
assertEquals(originalDevice.getRegistrationId(), parsedDevice.getRegistrationId());
|
||||
assertEquals(originalDevice.getPhoneNumberIdentityRegistrationId(),
|
||||
parsedDevice.getPhoneNumberIdentityRegistrationId());
|
||||
assertEquals(originalDevice.getCapabilities(), parsedDevice.getCapabilities());
|
||||
assertEquals(originalDevice.getFetchesMessages(), parsedDevice.getFetchesMessages());
|
||||
}
|
||||
|
||||
private void setReservationHash(final Account account, final byte[] reservedUsernameHash) {
|
||||
account.setReservedUsernameHash(reservedUsernameHash);
|
||||
}
|
||||
|
|
|
@ -183,13 +183,13 @@ class AccountsTest {
|
|||
accounts.create(account);
|
||||
|
||||
final UUID linkHandle = UUID.randomUUID();
|
||||
final byte[] encruptedUsername = RandomUtils.nextBytes(32);
|
||||
accountsManager.update(account, a -> a.setUsernameLinkDetails(linkHandle, encruptedUsername));
|
||||
final byte[] encryptedUsername = RandomUtils.nextBytes(32);
|
||||
accountsManager.update(account, a -> a.setUsernameLinkDetails(linkHandle, encryptedUsername));
|
||||
|
||||
final Optional<Account> maybeAccount = accountsManager.getByUsernameLinkHandle(linkHandle);
|
||||
assertTrue(maybeAccount.isPresent());
|
||||
assertTrue(maybeAccount.get().getEncryptedUsername().isPresent());
|
||||
assertArrayEquals(encruptedUsername, maybeAccount.get().getEncryptedUsername().get());
|
||||
assertArrayEquals(encryptedUsername, maybeAccount.get().getEncryptedUsername().get());
|
||||
|
||||
// making some unrelated change and updating account to check that username link data is still there
|
||||
final Optional<Account> accountToChange = accountsManager.getByAccountIdentifier(account.getUuid());
|
||||
|
@ -198,7 +198,7 @@ class AccountsTest {
|
|||
final Optional<Account> accountAfterChange = accountsManager.getByUsernameLinkHandle(linkHandle);
|
||||
assertTrue(accountAfterChange.isPresent());
|
||||
assertTrue(accountAfterChange.get().getEncryptedUsername().isPresent());
|
||||
assertArrayEquals(encruptedUsername, accountAfterChange.get().getEncryptedUsername().get());
|
||||
assertArrayEquals(encryptedUsername, accountAfterChange.get().getEncryptedUsername().get());
|
||||
|
||||
// now deleting the link
|
||||
final Optional<Account> accountToDeleteLink = accountsManager.getByAccountIdentifier(account.getUuid());
|
||||
|
|
|
@ -0,0 +1,48 @@
|
|||
{
|
||||
"number": "+14152222222",
|
||||
"usernameHash": null,
|
||||
"reservedUsernameHash": null,
|
||||
"usernameLinkHandle": null,
|
||||
"devices": [
|
||||
{
|
||||
"id": 1,
|
||||
"name": null,
|
||||
"authToken": null,
|
||||
"salt": null,
|
||||
"gcmId": null,
|
||||
"apnId": null,
|
||||
"voipApnId": null,
|
||||
"pushTimestamp": 0,
|
||||
"uninstalledFeedback": 0,
|
||||
"fetchesMessages": true,
|
||||
"registrationId": 1,
|
||||
"signedPreKey": {
|
||||
"keyId": 1,
|
||||
"publicKey": "BerKjYSh1PdniL5bhI9kwbH/Et3mx/8CypR1TYo/+d5o",
|
||||
"signature": "iK2yJkl0l6qe58Fy1dVo31X5sp6EiXSS5FZfa3W//E+Abylfa6ZRmM97CzTdXNu2DjgxZYF43G6HfJ49+99hgg"
|
||||
},
|
||||
"lastSeen" : 1692748800000,
|
||||
"created" : 1692718240137,
|
||||
"userAgent": null,
|
||||
"capabilities": null,
|
||||
"pniRegistrationId": 2,
|
||||
"pniSignedPreKey": {
|
||||
"keyId": 2,
|
||||
"publicKey": "BXcLL1VLft3tUnr/5UIW5Q0Hsr8/Az0CGJ+EuFqiXCYc",
|
||||
"signature": "YoKqyeOCHC0E9mqMoc1UPeyuLqGc8nvY+3D3YX5HC1bhxS48ZLYo40xql51A2CpIBqVmA+2gV3PXCV1Yhq4UAQ"
|
||||
}
|
||||
}
|
||||
],
|
||||
"identityKey": "BaMV4k/+jSn7jmHnRAPvfc7XBZOcayrhOmHFbGJwMyFS",
|
||||
"badges": [],
|
||||
"registrationLock": null,
|
||||
"registrationLockSalt": null,
|
||||
"version": 0,
|
||||
"pni": "22222222-2222-2222-2222-222222222222",
|
||||
"eu": null,
|
||||
"pniIdentityKey": "Bc0Myhpf2D+iCgUfIs+UStgffR/VGQRfP9mwFHI4U2x4",
|
||||
"cpv": null,
|
||||
"uak": "p5uWNi83Muqsd16PLi0/tQ==",
|
||||
"uua": true,
|
||||
"inCds": true
|
||||
}
|
Loading…
Reference in New Issue