Introduce "service identifiers"

This commit is contained in:
Jon Chambers
2023-07-21 09:34:10 -04:00
committed by GitHub
parent 4a6c7152cf
commit abb32bd919
39 changed files with 1304 additions and 588 deletions

View File

@@ -0,0 +1,77 @@
/*
* Copyright 2023 Signal Messenger, LLC
* SPDX-License-Identifier: AGPL-3.0-only
*/
package org.whispersystems.textsecuregcm.identity;
import static org.junit.jupiter.api.Assertions.assertArrayEquals;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
import java.nio.ByteBuffer;
import java.util.UUID;
import org.junit.jupiter.api.Test;
import org.whispersystems.textsecuregcm.util.UUIDUtil;
class AciServiceIdentifierTest {
@Test
void identityType() {
assertEquals(IdentityType.ACI, new AciServiceIdentifier(UUID.randomUUID()).identityType());
}
@Test
void toServiceIdentifierString() {
final UUID uuid = UUID.randomUUID();
assertEquals(uuid.toString(), new AciServiceIdentifier(uuid).toServiceIdentifierString());
}
@Test
void toCompactByteArray() {
final UUID uuid = UUID.randomUUID();
assertArrayEquals(UUIDUtil.toBytes(uuid), new AciServiceIdentifier(uuid).toCompactByteArray());
}
@Test
void toFixedWidthByteArray() {
final UUID uuid = UUID.randomUUID();
final ByteBuffer expectedBytesBuffer = ByteBuffer.allocate(17);
expectedBytesBuffer.put((byte) 0x00);
expectedBytesBuffer.putLong(uuid.getMostSignificantBits());
expectedBytesBuffer.putLong(uuid.getLeastSignificantBits());
expectedBytesBuffer.flip();
assertArrayEquals(expectedBytesBuffer.array(), new AciServiceIdentifier(uuid).toFixedWidthByteArray());
}
@Test
void valueOf() {
final UUID uuid = UUID.randomUUID();
assertEquals(uuid, AciServiceIdentifier.valueOf(uuid.toString()).uuid());
assertEquals(uuid, AciServiceIdentifier.valueOf("ACI:" + uuid).uuid());
assertThrows(IllegalArgumentException.class, () -> AciServiceIdentifier.valueOf("Not a valid UUID"));
assertThrows(IllegalArgumentException.class, () -> AciServiceIdentifier.valueOf("PNI:" + uuid));
}
@Test
void fromBytes() {
final UUID uuid = UUID.randomUUID();
assertEquals(uuid, AciServiceIdentifier.fromBytes(UUIDUtil.toBytes(uuid)).uuid());
final byte[] prefixedBytes = new byte[17];
prefixedBytes[0] = 0x00;
System.arraycopy(UUIDUtil.toBytes(uuid), 0, prefixedBytes, 1, 16);
assertEquals(uuid, AciServiceIdentifier.fromBytes(prefixedBytes).uuid());
prefixedBytes[0] = 0x01;
assertThrows(IllegalArgumentException.class, () -> AciServiceIdentifier.fromBytes(prefixedBytes));
}
}

View File

@@ -0,0 +1,71 @@
/*
* Copyright 2023 Signal Messenger, LLC
* SPDX-License-Identifier: AGPL-3.0-only
*/
package org.whispersystems.textsecuregcm.identity;
import static org.junit.jupiter.api.Assertions.assertArrayEquals;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
import java.nio.ByteBuffer;
import java.util.UUID;
import org.junit.jupiter.api.Test;
import org.whispersystems.textsecuregcm.util.UUIDUtil;
class PniServiceIdentifierTest {
@Test
void identityType() {
assertEquals(IdentityType.PNI, new PniServiceIdentifier(UUID.randomUUID()).identityType());
}
@Test
void toServiceIdentifierString() {
final UUID uuid = UUID.randomUUID();
assertEquals("PNI:" + uuid, new PniServiceIdentifier(uuid).toServiceIdentifierString());
}
@Test
void toByteArray() {
final UUID uuid = UUID.randomUUID();
final ByteBuffer expectedBytesBuffer = ByteBuffer.allocate(17);
expectedBytesBuffer.put((byte) 0x01);
expectedBytesBuffer.putLong(uuid.getMostSignificantBits());
expectedBytesBuffer.putLong(uuid.getLeastSignificantBits());
expectedBytesBuffer.flip();
assertArrayEquals(expectedBytesBuffer.array(), new PniServiceIdentifier(uuid).toCompactByteArray());
assertArrayEquals(expectedBytesBuffer.array(), new PniServiceIdentifier(uuid).toFixedWidthByteArray());
}
@Test
void valueOf() {
final UUID uuid = UUID.randomUUID();
assertEquals(uuid, PniServiceIdentifier.valueOf("PNI:" + uuid).uuid());
assertThrows(IllegalArgumentException.class, () -> PniServiceIdentifier.valueOf(uuid.toString()));
assertThrows(IllegalArgumentException.class, () -> PniServiceIdentifier.valueOf("Not a valid UUID"));
assertThrows(IllegalArgumentException.class, () -> PniServiceIdentifier.valueOf("ACI:" + uuid));
}
@Test
void fromBytes() {
final UUID uuid = UUID.randomUUID();
assertThrows(IllegalArgumentException.class, () -> PniServiceIdentifier.fromBytes(UUIDUtil.toBytes(uuid)));
final byte[] prefixedBytes = new byte[17];
prefixedBytes[0] = 0x00;
System.arraycopy(UUIDUtil.toBytes(uuid), 0, prefixedBytes, 1, 16);
assertThrows(IllegalArgumentException.class, () -> PniServiceIdentifier.fromBytes(prefixedBytes));
prefixedBytes[0] = 0x01;
assertEquals(uuid, PniServiceIdentifier.fromBytes(prefixedBytes).uuid());
}
}

View File

@@ -0,0 +1,87 @@
/*
* Copyright 2023 Signal Messenger, LLC
* SPDX-License-Identifier: AGPL-3.0-only
*/
package org.whispersystems.textsecuregcm.identity;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
import java.util.UUID;
import java.util.stream.Stream;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;
import org.junit.jupiter.params.provider.ValueSource;
import org.whispersystems.textsecuregcm.util.UUIDUtil;
class ServiceIdentifierTest {
@ParameterizedTest
@MethodSource
void valueOf(final String identifierString, final IdentityType expectedIdentityType, final UUID expectedUuid) {
final ServiceIdentifier serviceIdentifier = ServiceIdentifier.valueOf(identifierString);
assertEquals(expectedIdentityType, serviceIdentifier.identityType());
assertEquals(expectedUuid, serviceIdentifier.uuid());
}
private static Stream<Arguments> valueOf() {
final UUID uuid = UUID.randomUUID();
return Stream.of(
Arguments.of(uuid.toString(), IdentityType.ACI, uuid),
Arguments.of("ACI:" + uuid, IdentityType.ACI, uuid),
Arguments.of("PNI:" + uuid, IdentityType.PNI, uuid));
}
@ParameterizedTest
@ValueSource(strings = {"Not a valid UUID", "BAD:a9edc243-3e93-45d4-95c6-e3a84cd4a254"})
void valueOfIllegalArgument(final String identifierString) {
assertThrows(IllegalArgumentException.class, () -> ServiceIdentifier.valueOf(identifierString));
}
@ParameterizedTest
@MethodSource
void fromBytes(final byte[] bytes, final IdentityType expectedIdentityType, final UUID expectedUuid) {
final ServiceIdentifier serviceIdentifier = ServiceIdentifier.fromBytes(bytes);
assertEquals(expectedIdentityType, serviceIdentifier.identityType());
assertEquals(expectedUuid, serviceIdentifier.uuid());
}
private static Stream<Arguments> fromBytes() {
final UUID uuid = UUID.randomUUID();
final byte[] aciPrefixedBytes = new byte[17];
aciPrefixedBytes[0] = 0x00;
System.arraycopy(UUIDUtil.toBytes(uuid), 0, aciPrefixedBytes, 1, 16);
final byte[] pniPrefixedBytes = new byte[17];
pniPrefixedBytes[0] = 0x01;
System.arraycopy(UUIDUtil.toBytes(uuid), 0, pniPrefixedBytes, 1, 16);
return Stream.of(
Arguments.of(UUIDUtil.toBytes(uuid), IdentityType.ACI, uuid),
Arguments.of(aciPrefixedBytes, IdentityType.ACI, uuid),
Arguments.of(pniPrefixedBytes, IdentityType.PNI, uuid));
}
@ParameterizedTest
@MethodSource
void fromBytesIllegalArgument(final byte[] bytes) {
assertThrows(IllegalArgumentException.class, () -> ServiceIdentifier.fromBytes(bytes));
}
private static Stream<Arguments> fromBytesIllegalArgument() {
final byte[] invalidPrefixBytes = new byte[17];
invalidPrefixBytes[0] = (byte) 0xff;
return Stream.of(
Arguments.of(new byte[0]),
Arguments.of(new byte[15]),
Arguments.of(new byte[18]),
Arguments.of(invalidPrefixBytes));
}
}