diff --git a/service/src/main/java/org/whispersystems/textsecuregcm/controllers/CallRoutingController.java b/service/src/main/java/org/whispersystems/textsecuregcm/controllers/CallRoutingController.java index 0ec9f231a..f158149a8 100644 --- a/service/src/main/java/org/whispersystems/textsecuregcm/controllers/CallRoutingController.java +++ b/service/src/main/java/org/whispersystems/textsecuregcm/controllers/CallRoutingController.java @@ -79,7 +79,7 @@ public class CallRoutingController { UUID aci = auth.getAccount().getUuid(); rateLimiters.getCallEndpointLimiter().validate(aci); - if (experimentEnrollmentManager.isEnrolled(aci, "cloudflareTurn")) { + if (experimentEnrollmentManager.isEnrolled(auth.getAccount().getNumber(), aci, "cloudflareTurn")) { return cloudflareTurnCredentialsManager.retrieveFromCloudflare(); } diff --git a/service/src/main/java/org/whispersystems/textsecuregcm/experiment/ExperimentEnrollmentManager.java b/service/src/main/java/org/whispersystems/textsecuregcm/experiment/ExperimentEnrollmentManager.java index b06267d7c..cf95dead8 100644 --- a/service/src/main/java/org/whispersystems/textsecuregcm/experiment/ExperimentEnrollmentManager.java +++ b/service/src/main/java/org/whispersystems/textsecuregcm/experiment/ExperimentEnrollmentManager.java @@ -40,16 +40,29 @@ public class ExperimentEnrollmentManager { final Optional maybeConfiguration = dynamicConfigurationManager .getConfiguration().getExperimentEnrollmentConfiguration(experimentName); - return maybeConfiguration.map(config -> { + return maybeConfiguration + .map(config -> isAccountEnrolled(accountUuid, config) + .orElse(isEnrolled(accountUuid, config.getEnrollmentPercentage(), experimentName)) + ).orElse(false); + } - if (config.getUuidSelector().getUuids().contains(accountUuid)) { - final int r = random.nextInt(100); - return r < config.getUuidSelector().getUuidEnrollmentPercentage(); - } + Optional isAccountEnrolled(final UUID accountUuid, DynamicExperimentEnrollmentConfiguration config) { + if (config.getUuidSelector().getUuids().contains(accountUuid)) { + final int r = random.nextInt(100); + return Optional.of(r < config.getUuidSelector().getUuidEnrollmentPercentage()); + } - return isEnrolled(accountUuid, config.getEnrollmentPercentage(), experimentName); + return Optional.empty(); + } - }).orElse(false); + public boolean isEnrolled(final String e164, final UUID accountUuid, final String experimentName) { + + final Optional maybeConfiguration = dynamicConfigurationManager + .getConfiguration().getExperimentEnrollmentConfiguration(experimentName); + + return maybeConfiguration + .flatMap(config -> isAccountEnrolled(accountUuid, config)) + .orElse(isEnrolled(e164, experimentName)); } public boolean isEnrolled(final String e164, final String experimentName) { diff --git a/service/src/test/java/org/whispersystems/textsecuregcm/controllers/CallRoutingControllerTest.java b/service/src/test/java/org/whispersystems/textsecuregcm/controllers/CallRoutingControllerTest.java index dabe5833d..1a91349c4 100644 --- a/service/src/test/java/org/whispersystems/textsecuregcm/controllers/CallRoutingControllerTest.java +++ b/service/src/test/java/org/whispersystems/textsecuregcm/controllers/CallRoutingControllerTest.java @@ -116,7 +116,7 @@ class CallRoutingControllerTest { @Test void testGetTurnEndpointsCloudflare() throws IOException { - when(experimentEnrollmentManager.isEnrolled(AuthHelper.VALID_UUID, "cloudflareTurn")) + when(experimentEnrollmentManager.isEnrolled(AuthHelper.VALID_NUMBER, AuthHelper.VALID_UUID, "cloudflareTurn")) .thenReturn(true); when(cloudflareTurnCredentialsManager.retrieveFromCloudflare()).thenReturn(new TurnToken("ABC", "XYZ", diff --git a/service/src/test/java/org/whispersystems/textsecuregcm/experiment/ExperimentEnrollmentManagerTest.java b/service/src/test/java/org/whispersystems/textsecuregcm/experiment/ExperimentEnrollmentManagerTest.java index 30fa3f720..45a7fea6c 100644 --- a/service/src/test/java/org/whispersystems/textsecuregcm/experiment/ExperimentEnrollmentManagerTest.java +++ b/service/src/test/java/org/whispersystems/textsecuregcm/experiment/ExperimentEnrollmentManagerTest.java @@ -46,7 +46,9 @@ class ExperimentEnrollmentManagerTest { private static final UUID ACCOUNT_UUID = UUID.randomUUID(); private static final String UUID_EXPERIMENT_NAME = "uuid_test"; + private static final String E164_AND_UUID_EXPERIMENT_NAME = "e164_uuid_test"; + private static final String NOT_ENROLLED_164 = "+632025551212"; private static final String ENROLLED_164 = "+12025551212"; private static final String EXCLUDED_164 = "+18005551212"; private static final String E164_EXPERIMENT_NAME = "e164_test"; @@ -71,6 +73,10 @@ class ExperimentEnrollmentManagerTest { .thenReturn(Optional.of(experimentEnrollmentConfiguration)); when(dynamicConfiguration.getPreRegistrationEnrollmentConfiguration(E164_EXPERIMENT_NAME)) .thenReturn(Optional.of(preRegistrationExperimentEnrollmentConfiguration)); + when(dynamicConfiguration.getExperimentEnrollmentConfiguration(E164_AND_UUID_EXPERIMENT_NAME)) + .thenReturn(Optional.of(experimentEnrollmentConfiguration)); + when(dynamicConfiguration.getPreRegistrationEnrollmentConfiguration(E164_AND_UUID_EXPERIMENT_NAME)) + .thenReturn(Optional.of(preRegistrationExperimentEnrollmentConfiguration)); account = mock(Account.class); when(account.getUuid()).thenReturn(ACCOUNT_UUID); @@ -112,6 +118,29 @@ class ExperimentEnrollmentManagerTest { assertEquals(75, counts.get(true)); } + @Test + void testIsEnrolled_E164AndUuidExperiment() { + when(preRegistrationExperimentEnrollmentConfiguration.getIncludedCountryCodes()).thenReturn(Set.of("1")); + when(preRegistrationExperimentEnrollmentConfiguration.getEnrollmentPercentage()).thenReturn(0); + when(preRegistrationExperimentEnrollmentConfiguration.getEnrolledE164s()).thenReturn(Collections.emptySet()); + when(preRegistrationExperimentEnrollmentConfiguration.getExcludedE164s()).thenReturn(Collections.emptySet()); + when(preRegistrationExperimentEnrollmentConfiguration.getExcludedCountryCodes()).thenReturn(Collections.emptySet()); + + when(uuidSelector.getUuids()).thenReturn(Set.of(ACCOUNT_UUID)); + when(uuidSelector.getUuidEnrollmentPercentage()).thenReturn(100); + assertTrue(experimentEnrollmentManager.isEnrolled(NOT_ENROLLED_164, account.getUuid(), E164_AND_UUID_EXPERIMENT_NAME)); + when(uuidSelector.getUuidEnrollmentPercentage()).thenReturn(0); + assertFalse(experimentEnrollmentManager.isEnrolled(NOT_ENROLLED_164, account.getUuid(), E164_AND_UUID_EXPERIMENT_NAME)); + assertFalse(experimentEnrollmentManager.isEnrolled(ENROLLED_164, account.getUuid(), E164_AND_UUID_EXPERIMENT_NAME)); + + when(uuidSelector.getUuids()).thenReturn(Collections.emptySet()); + assertTrue(experimentEnrollmentManager.isEnrolled(ENROLLED_164, account.getUuid(), E164_AND_UUID_EXPERIMENT_NAME)); + assertFalse(experimentEnrollmentManager.isEnrolled(NOT_ENROLLED_164, account.getUuid(), E164_AND_UUID_EXPERIMENT_NAME)); + when(preRegistrationExperimentEnrollmentConfiguration.getEnrollmentPercentage()).thenReturn(100); + assertTrue(experimentEnrollmentManager.isEnrolled(ENROLLED_164, account.getUuid(), E164_AND_UUID_EXPERIMENT_NAME)); + assertTrue(experimentEnrollmentManager.isEnrolled(NOT_ENROLLED_164, account.getUuid(), E164_AND_UUID_EXPERIMENT_NAME)); + } + @ParameterizedTest @MethodSource void testIsEnrolled_PreRegistrationExperiment(final String e164, final String experimentName,