Zero-pad discriminators less than initial width

This commit is contained in:
Ravi Khadiwala 2022-08-19 16:28:40 -05:00 committed by Chris Eager
parent 628a112b38
commit 1891622e69
3 changed files with 18 additions and 7 deletions

View File

@ -70,7 +70,7 @@ public class UsernameGenerator {
// check discriminators of the current width up to attemptsPerWidth times
for (int i = 0; i < attemptsPerWidth; i++) {
int discriminator = ThreadLocalRandom.current().nextInt(rangeMin, rangeMax);
String username = UsernameGenerator.fromParts(nickname, discriminator);
String username = fromParts(nickname, discriminator);
attempts++;
if (usernameAvailableFun.test(username)) {
DISCRIMINATOR_ATTEMPT_COUNTER.record(attempts);
@ -101,11 +101,12 @@ public class UsernameGenerator {
/**
* Generate a username from a nickname and discriminator
*/
public static String fromParts(final String nickname, final int discriminator) throws IllegalArgumentException {
public String fromParts(final String nickname, final int discriminator) throws IllegalArgumentException {
if (!isValidNickname(nickname)) {
throw new IllegalArgumentException("Invalid nickname " + nickname);
}
return nickname + SEPARATOR + discriminator;
// zero pad discriminators less than the discriminator initial width
return String.format("%s#%0" + initialWidth + "d", nickname, discriminator);
}
public static boolean isValidNickname(final String nickname) {

View File

@ -64,6 +64,7 @@ class AccountsManagerUsernameIntegrationTest {
private AccountsManager accountsManager;
private Accounts accounts;
private UsernameGenerator usernameGenerator;
@BeforeEach
void setup() throws InterruptedException {
@ -141,6 +142,7 @@ class AccountsManagerUsernameIntegrationTest {
when(experimentEnrollmentManager.isEnrolled(any(UUID.class), eq(AccountsManager.USERNAME_EXPERIMENT_NAME)))
.thenReturn(true);
usernameGenerator = new UsernameGenerator(1, 2, 10);
accountsManager = new AccountsManager(
accounts,
phoneNumberIdentifiers,
@ -155,7 +157,7 @@ class AccountsManagerUsernameIntegrationTest {
mock(SecureStorageClient.class),
mock(SecureBackupClient.class),
mock(ClientPresenceManager.class),
new UsernameGenerator(1, 2, 10),
usernameGenerator,
experimentEnrollmentManager,
mock(Clock.class));
}
@ -197,7 +199,7 @@ class AccountsManagerUsernameIntegrationTest {
.tableName(USERNAMES_TABLE_NAME)
.item(Map.of(
Accounts.KEY_ACCOUNT_UUID, AttributeValues.fromUUID(UUID.randomUUID()),
Accounts.ATTR_USERNAME, AttributeValues.fromString(UsernameGenerator.fromParts("n00bkiller", i))))
Accounts.ATTR_USERNAME, AttributeValues.fromString(usernameGenerator.fromParts("n00bkiller", i))))
.build());
}
assertThrows(UsernameNotAvailableException.class, () -> accountsManager.setUsername(account, "n00bkiller", null));
@ -213,7 +215,7 @@ class AccountsManagerUsernameIntegrationTest {
.tableName(USERNAMES_TABLE_NAME)
.item(Map.of(
Accounts.KEY_ACCOUNT_UUID, AttributeValues.fromUUID(UUID.randomUUID()),
Accounts.ATTR_USERNAME, AttributeValues.fromString(UsernameGenerator.fromParts("n00bkiller", i))))
Accounts.ATTR_USERNAME, AttributeValues.fromString(usernameGenerator.fromParts("n00bkiller", i))))
.build());
}

View File

@ -5,7 +5,6 @@ import org.junit.jupiter.api.Test;
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.storage.UsernameNotAvailableException;
import org.whispersystems.textsecuregcm.util.UsernameGenerator;
@ -63,6 +62,15 @@ public class UsernameGeneratorTest {
);
}
@Test
public void zeroPadDiscriminators() {
final UsernameGenerator generator = new UsernameGenerator(4, 5, 1);
assertThat(generator.fromParts("test", 1)).isEqualTo("test#0001");
assertThat(generator.fromParts("test", 123)).isEqualTo("test#0123");
assertThat(generator.fromParts("test", 9999)).isEqualTo("test#9999");
assertThat(generator.fromParts("test", 99999)).isEqualTo("test#99999");
}
@Test
public void expectedWidth() throws UsernameNotAvailableException {
String username = new UsernameGenerator(1, 6, 1).generateAvailableUsername("test", t -> true);