From 25f603efc9a16306ae613a81ed5db1b539237a0b Mon Sep 17 00:00:00 2001 From: Chris Eager Date: Tue, 9 Mar 2021 17:53:49 -0600 Subject: [PATCH] Add DynamicPreRegistrationExperimentEnrollmentConfiguration --- .../dynamic/DynamicConfiguration.java | 9 +++ ...tionExperimentEnrollmentConfiguration.java | 50 +++++++++++++ .../dynamic/DynamicConfigurationTest.java | 74 +++++++++++++++++++ 3 files changed, 133 insertions(+) create mode 100644 service/src/main/java/org/whispersystems/textsecuregcm/configuration/dynamic/DynamicPreRegistrationExperimentEnrollmentConfiguration.java diff --git a/service/src/main/java/org/whispersystems/textsecuregcm/configuration/dynamic/DynamicConfiguration.java b/service/src/main/java/org/whispersystems/textsecuregcm/configuration/dynamic/DynamicConfiguration.java index d1349b206..f2b2c3dec 100644 --- a/service/src/main/java/org/whispersystems/textsecuregcm/configuration/dynamic/DynamicConfiguration.java +++ b/service/src/main/java/org/whispersystems/textsecuregcm/configuration/dynamic/DynamicConfiguration.java @@ -14,6 +14,10 @@ public class DynamicConfiguration { @Valid private Map experiments = Collections.emptyMap(); + @JsonProperty + @Valid + private Map preRegistrationExperiments = Collections.emptyMap(); + @JsonProperty @Valid private DynamicRateLimitsConfiguration limits = new DynamicRateLimitsConfiguration(); @@ -38,6 +42,11 @@ public class DynamicConfiguration { return Optional.ofNullable(experiments.get(experimentName)); } + public Optional getPreRegistrationEnrollmentConfiguration( + final String experimentName) { + return Optional.ofNullable(preRegistrationExperiments.get(experimentName)); + } + public DynamicRateLimitsConfiguration getLimits() { return limits; } diff --git a/service/src/main/java/org/whispersystems/textsecuregcm/configuration/dynamic/DynamicPreRegistrationExperimentEnrollmentConfiguration.java b/service/src/main/java/org/whispersystems/textsecuregcm/configuration/dynamic/DynamicPreRegistrationExperimentEnrollmentConfiguration.java new file mode 100644 index 000000000..4a5eae09c --- /dev/null +++ b/service/src/main/java/org/whispersystems/textsecuregcm/configuration/dynamic/DynamicPreRegistrationExperimentEnrollmentConfiguration.java @@ -0,0 +1,50 @@ +/* + * Copyright 2021 Signal Messenger, LLC + * SPDX-License-Identifier: AGPL-3.0-only + */ + +package org.whispersystems.textsecuregcm.configuration.dynamic; + +import com.fasterxml.jackson.annotation.JsonProperty; +import java.util.Collections; +import java.util.Set; +import javax.validation.Valid; +import javax.validation.constraints.Max; +import javax.validation.constraints.Min; + +public class DynamicPreRegistrationExperimentEnrollmentConfiguration { + + @JsonProperty + @Valid + private Set enrolledE164s = Collections.emptySet(); + + @JsonProperty + @Valid + private Set excludedCountryCodes = Collections.emptySet(); + + @JsonProperty + @Valid + private Set includedCountryCodes = Collections.emptySet(); + + @JsonProperty + @Valid + @Min(0) + @Max(100) + private int enrollmentPercentage = 0; + + public Set getEnrolledE164s() { + return enrolledE164s; + } + + public Set getExcludedCountryCodes() { + return excludedCountryCodes; + } + + public Set getIncludedCountryCodes() { + return includedCountryCodes; + } + + public int getEnrollmentPercentage() { + return enrollmentPercentage; + } +} diff --git a/service/src/test/java/org/whispersystems/textsecuregcm/configuration/dynamic/DynamicConfigurationTest.java b/service/src/test/java/org/whispersystems/textsecuregcm/configuration/dynamic/DynamicConfigurationTest.java index af8f6f2c1..62e98f99b 100644 --- a/service/src/test/java/org/whispersystems/textsecuregcm/configuration/dynamic/DynamicConfigurationTest.java +++ b/service/src/test/java/org/whispersystems/textsecuregcm/configuration/dynamic/DynamicConfigurationTest.java @@ -15,6 +15,7 @@ import com.vdurmont.semver4j.Semver; import java.util.Collections; import java.util.List; import java.util.Map; +import java.util.Optional; import java.util.Set; import java.util.UUID; import org.junit.jupiter.api.Test; @@ -71,6 +72,79 @@ class DynamicConfigurationTest { } } + @Test + void testParsePreRegistrationExperiments() throws JsonProcessingException { + { + final String emptyConfigYaml = "test: true"; + final DynamicConfiguration emptyConfig = DynamicConfigurationManager.OBJECT_MAPPER + .readValue(emptyConfigYaml, DynamicConfiguration.class); + + assertFalse(emptyConfig.getPreRegistrationEnrollmentConfiguration("test").isPresent()); + } + + { + final String experimentConfigYaml = + "preRegistrationExperiments:\n" + + " percentageOnly:\n" + + " enrollmentPercentage: 17\n" + + " e164sCountryCodesAndPercentage:\n" + + " enrolledE164s:\n" + + " - +120255551212\n" + + " - +3655323174\n" + + " enrollmentPercentage: 46\n" + + " excludedCountryCodes:\n" + + " - 47\n" + + " includedCountryCodes:\n" + + " - 56\n" + + " e164sAndExcludedCodes:\n" + + " enrolledE164s:\n" + + " - +120255551212\n" + + " excludedCountryCodes:\n" + + " - 47"; + + final DynamicConfiguration config = DynamicConfigurationManager.OBJECT_MAPPER + .readValue(experimentConfigYaml, DynamicConfiguration.class); + + assertFalse(config.getPreRegistrationEnrollmentConfiguration("unconfigured").isPresent()); + + { + final Optional percentageOnly = config + .getPreRegistrationEnrollmentConfiguration("percentageOnly"); + assertTrue(percentageOnly.isPresent()); + assertEquals(17, + percentageOnly.get().getEnrollmentPercentage()); + assertEquals(Collections.emptySet(), + percentageOnly.get().getEnrolledE164s()); + } + + { + final Optional e164sCountryCodesAndPercentage = config + .getPreRegistrationEnrollmentConfiguration("e164sCountryCodesAndPercentage"); + + assertTrue(e164sCountryCodesAndPercentage.isPresent()); + assertEquals(46, + e164sCountryCodesAndPercentage.get().getEnrollmentPercentage()); + assertEquals(Set.of("+120255551212", "+3655323174"), + e164sCountryCodesAndPercentage.get().getEnrolledE164s()); + assertEquals(Set.of("47"), + e164sCountryCodesAndPercentage.get().getExcludedCountryCodes()); + assertEquals(Set.of("56"), + e164sCountryCodesAndPercentage.get().getIncludedCountryCodes()); + } + + { + final Optional e164sAndExcludedCodes = config + .getPreRegistrationEnrollmentConfiguration("e164sAndExcludedCodes"); + assertTrue(e164sAndExcludedCodes.isPresent()); + assertEquals(0, e164sAndExcludedCodes.get().getEnrollmentPercentage()); + assertEquals(Set.of("+120255551212"), + e164sAndExcludedCodes.get().getEnrolledE164s()); + assertEquals(Set.of("47"), + e164sAndExcludedCodes.get().getExcludedCountryCodes()); + } + } + } + @Test void testParseRemoteDeprecationConfig() throws JsonProcessingException { {