mirror of
https://github.com/signalapp/Signal-Server
synced 2026-04-21 18:48:06 +01:00
Make TURN configuration dynamic
Also enables conditionally including more TURN servers for gradual rollouts
This commit is contained in:
committed by
ravi-signal
parent
8541360bf3
commit
c70d7535b9
@@ -0,0 +1,133 @@
|
||||
package org.whispersystems.textsecuregcm.auth;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.whispersystems.textsecuregcm.configuration.dynamic.DynamicConfiguration;
|
||||
import org.whispersystems.textsecuregcm.storage.DynamicConfigurationManager;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
public class TurnTokenGeneratorTest {
|
||||
|
||||
@Test
|
||||
public void testAlwaysSelectFirst() throws JsonProcessingException {
|
||||
final String configString = """
|
||||
captcha:
|
||||
scoreFloor: 1.0
|
||||
turn:
|
||||
secret: bloop
|
||||
uriConfigs:
|
||||
- uris:
|
||||
- always1.org
|
||||
- always2.org
|
||||
- uris:
|
||||
- never.org
|
||||
weight: 0
|
||||
""";
|
||||
DynamicConfiguration config = DynamicConfigurationManager
|
||||
.parseConfiguration(configString, DynamicConfiguration.class)
|
||||
.orElseThrow();
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
DynamicConfigurationManager<DynamicConfiguration> mockDynamicConfigManager = mock(
|
||||
DynamicConfigurationManager.class);
|
||||
|
||||
when(mockDynamicConfigManager.getConfiguration()).thenReturn(config);
|
||||
final TurnTokenGenerator turnTokenGenerator = new TurnTokenGenerator(mockDynamicConfigManager);
|
||||
|
||||
final long COUNT = 1000;
|
||||
|
||||
final Map<String, Long> urlCounts = Stream
|
||||
.generate(() -> turnTokenGenerator.generate(""))
|
||||
.limit(COUNT)
|
||||
.flatMap(token -> token.getUrls().stream())
|
||||
.collect(Collectors.groupingBy(i -> i, Collectors.counting()));
|
||||
|
||||
assertThat(urlCounts.get("always1.org")).isEqualTo(COUNT);
|
||||
assertThat(urlCounts.get("always2.org")).isEqualTo(COUNT);
|
||||
assertThat(urlCounts).doesNotContainKey("never.org");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testProbabilisticUrls() throws JsonProcessingException {
|
||||
final String configString = """
|
||||
captcha:
|
||||
scoreFloor: 1.0
|
||||
turn:
|
||||
secret: bloop
|
||||
uriConfigs:
|
||||
- uris:
|
||||
- always.org
|
||||
- sometimes1.org
|
||||
weight: 5
|
||||
- uris:
|
||||
- always.org
|
||||
- sometimes2.org
|
||||
weight: 5
|
||||
""";
|
||||
DynamicConfiguration config = DynamicConfigurationManager
|
||||
.parseConfiguration(configString, DynamicConfiguration.class)
|
||||
.orElseThrow();
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
DynamicConfigurationManager<DynamicConfiguration> mockDynamicConfigManager = mock(
|
||||
DynamicConfigurationManager.class);
|
||||
|
||||
when(mockDynamicConfigManager.getConfiguration()).thenReturn(config);
|
||||
final TurnTokenGenerator turnTokenGenerator = new TurnTokenGenerator(mockDynamicConfigManager);
|
||||
|
||||
final long COUNT = 1000;
|
||||
|
||||
final Map<String, Long> urlCounts = Stream
|
||||
.generate(() -> turnTokenGenerator.generate(""))
|
||||
.limit(COUNT)
|
||||
.flatMap(token -> token.getUrls().stream())
|
||||
.collect(Collectors.groupingBy(i -> i, Collectors.counting()));
|
||||
|
||||
assertThat(urlCounts.get("always.org")).isEqualTo(COUNT);
|
||||
assertThat(urlCounts.get("sometimes1.org")).isGreaterThan(0);
|
||||
assertThat(urlCounts.get("sometimes2.org")).isGreaterThan(0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExplicitEnrollment() throws JsonProcessingException {
|
||||
final String configString = """
|
||||
captcha:
|
||||
scoreFloor: 1.0
|
||||
turn:
|
||||
secret: bloop
|
||||
uriConfigs:
|
||||
- uris:
|
||||
- enrolled.org
|
||||
weight: 0
|
||||
enrolledNumbers:
|
||||
- +15555555555
|
||||
- uris:
|
||||
- unenrolled.org
|
||||
weight: 1
|
||||
""";
|
||||
DynamicConfiguration config = DynamicConfigurationManager
|
||||
.parseConfiguration(configString, DynamicConfiguration.class)
|
||||
.orElseThrow();
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
DynamicConfigurationManager<DynamicConfiguration> mockDynamicConfigManager = mock(
|
||||
DynamicConfigurationManager.class);
|
||||
|
||||
when(mockDynamicConfigManager.getConfiguration()).thenReturn(config);
|
||||
|
||||
final TurnTokenGenerator turnTokenGenerator = new TurnTokenGenerator(mockDynamicConfigManager);
|
||||
TurnToken token = turnTokenGenerator.generate("+15555555555");
|
||||
assertThat(token.getUrls().get(0)).isEqualTo("enrolled.org");
|
||||
token = turnTokenGenerator.generate("+15555555556");
|
||||
assertThat(token.getUrls().get(0)).isEqualTo("unenrolled.org");
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -395,4 +395,46 @@ class DynamicConfigurationTest {
|
||||
assertThat(directoryReconcilerConfiguration.isEnabled()).isFalse();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void testParseTurnConfig() throws JsonProcessingException {
|
||||
{
|
||||
final String config = REQUIRED_CONFIG.concat("""
|
||||
turn:
|
||||
secret: bloop
|
||||
uriConfigs:
|
||||
- uris:
|
||||
- turn:test.org
|
||||
weight: -1
|
||||
""");
|
||||
assertThat(DynamicConfigurationManager.parseConfiguration(config, DynamicConfiguration.class)).isEmpty();
|
||||
}
|
||||
{
|
||||
final String config = REQUIRED_CONFIG.concat("""
|
||||
turn:
|
||||
secret: bloop
|
||||
uriConfigs:
|
||||
- uris:
|
||||
- turn:test0.org
|
||||
- turn:test1.org
|
||||
- uris:
|
||||
- turn:test2.org
|
||||
weight: 2
|
||||
enrolledNumbers:
|
||||
- +15555555555
|
||||
""");
|
||||
DynamicTurnConfiguration turnConfiguration = DynamicConfigurationManager
|
||||
.parseConfiguration(config, DynamicConfiguration.class)
|
||||
.orElseThrow()
|
||||
.getTurnConfiguration();
|
||||
assertThat(turnConfiguration.getSecret()).isEqualTo("bloop");
|
||||
assertThat(turnConfiguration.getUriConfigs().get(0).getUris()).hasSize(2);
|
||||
assertThat(turnConfiguration.getUriConfigs().get(1).getUris()).hasSize(1);
|
||||
assertThat(turnConfiguration.getUriConfigs().get(0).getWeight()).isEqualTo(1);
|
||||
assertThat(turnConfiguration.getUriConfigs().get(1).getWeight()).isEqualTo(2);
|
||||
assertThat(turnConfiguration.getUriConfigs().get(1).getEnrolledNumbers()).containsExactly("+15555555555");
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
package org.whispersystems.textsecuregcm.util;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
public class WeightedRandomSelectTest {
|
||||
|
||||
@Test
|
||||
public void test5050() {
|
||||
final WeightedRandomSelect<String> selector = new WeightedRandomSelect<>(
|
||||
List.of(new Pair<>("a", 1L), new Pair<>("b", 1L)));
|
||||
final Map<String, Long> counts = Stream.generate(selector::select)
|
||||
.limit(1000)
|
||||
.collect(Collectors.groupingBy(s -> s, Collectors.counting()));
|
||||
assertThat(counts.get("a")).isGreaterThan(1);
|
||||
assertThat(counts.get("b")).isGreaterThan(1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAlways() {
|
||||
final WeightedRandomSelect<String> selector = new WeightedRandomSelect<>(
|
||||
List.of(new Pair<>("a", 1L), new Pair<>("b", 0L)));
|
||||
final Map<String, Long> counts = Stream.generate(selector::select)
|
||||
.limit(1000)
|
||||
.collect(Collectors.groupingBy(s -> s, Collectors.counting()));
|
||||
assertThat(counts.get("a")).isEqualTo(1000);
|
||||
assertThat(counts).doesNotContainKey("b");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testThree() {
|
||||
final WeightedRandomSelect<String> selector = new WeightedRandomSelect<>(
|
||||
List.of(new Pair<>("a", 33L), new Pair<>("b", 33L), new Pair<>("c", 33L)));
|
||||
final Map<String, Long> counts = Stream.generate(selector::select)
|
||||
.limit(1000)
|
||||
.collect(Collectors.groupingBy(s -> s, Collectors.counting()));
|
||||
assertThat(counts.get("a")).isGreaterThan(1);
|
||||
assertThat(counts.get("b")).isGreaterThan(1);
|
||||
assertThat(counts.get("c")).isGreaterThan(1);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user