Migrate from `Object[]` parameters to `Stream<Arguments>`
This commit is contained in:
parent
f45a1c232f
commit
bb27dd0c3b
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2013-2020 Signal Messenger, LLC
|
* Copyright 2013-2022 Signal Messenger, LLC
|
||||||
* SPDX-License-Identifier: AGPL-3.0-only
|
* SPDX-License-Identifier: AGPL-3.0-only
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -20,112 +20,121 @@ import java.util.concurrent.ExecutorService;
|
||||||
import java.util.concurrent.Executors;
|
import java.util.concurrent.Executors;
|
||||||
import java.util.concurrent.RejectedExecutionException;
|
import java.util.concurrent.RejectedExecutionException;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
import java.util.stream.Stream;
|
||||||
import org.junit.jupiter.api.BeforeEach;
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.junit.jupiter.params.ParameterizedTest;
|
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.MethodSource;
|
||||||
|
|
||||||
class ExperimentTest {
|
class ExperimentTest {
|
||||||
|
|
||||||
private Timer matchTimer;
|
private Timer matchTimer;
|
||||||
private Timer errorTimer;
|
private Timer errorTimer;
|
||||||
|
|
||||||
private Experiment experiment;
|
private Experiment experiment;
|
||||||
|
|
||||||
@BeforeEach
|
@BeforeEach
|
||||||
void setUp() {
|
void setUp() {
|
||||||
matchTimer = mock(Timer.class);
|
matchTimer = mock(Timer.class);
|
||||||
errorTimer = mock(Timer.class);
|
errorTimer = mock(Timer.class);
|
||||||
|
|
||||||
experiment = new Experiment("test", matchTimer, errorTimer, mock(Timer.class), mock(Timer.class), mock(Timer.class));
|
experiment = new Experiment("test", matchTimer, errorTimer, mock(Timer.class), mock(Timer.class),
|
||||||
}
|
mock(Timer.class));
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void compareFutureResult() {
|
void compareFutureResult() {
|
||||||
experiment.compareFutureResult(12, CompletableFuture.completedFuture(12));
|
experiment.compareFutureResult(12, CompletableFuture.completedFuture(12));
|
||||||
verify(matchTimer).record(anyLong(), eq(TimeUnit.NANOSECONDS));
|
verify(matchTimer).record(anyLong(), eq(TimeUnit.NANOSECONDS));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void compareFutureResultError() {
|
void compareFutureResultError() {
|
||||||
experiment.compareFutureResult(12, CompletableFuture.failedFuture(new RuntimeException("OH NO")));
|
experiment.compareFutureResult(12, CompletableFuture.failedFuture(new RuntimeException("OH NO")));
|
||||||
verify(errorTimer).record(anyLong(), eq(TimeUnit.NANOSECONDS));
|
verify(errorTimer).record(anyLong(), eq(TimeUnit.NANOSECONDS));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void compareSupplierResultMatch() {
|
void compareSupplierResultMatch() {
|
||||||
experiment.compareSupplierResult(12, () -> 12);
|
experiment.compareSupplierResult(12, () -> 12);
|
||||||
verify(matchTimer).record(anyLong(), eq(TimeUnit.NANOSECONDS));
|
verify(matchTimer).record(anyLong(), eq(TimeUnit.NANOSECONDS));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void compareSupplierResultError() {
|
void compareSupplierResultError() {
|
||||||
experiment.compareSupplierResult(12, () -> { throw new RuntimeException("OH NO"); });
|
experiment.compareSupplierResult(12, () -> {
|
||||||
verify(errorTimer).record(anyLong(), eq(TimeUnit.NANOSECONDS));
|
throw new RuntimeException("OH NO");
|
||||||
}
|
});
|
||||||
|
verify(errorTimer).record(anyLong(), eq(TimeUnit.NANOSECONDS));
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void compareSupplierResultAsyncMatch() throws InterruptedException {
|
void compareSupplierResultAsyncMatch() throws InterruptedException {
|
||||||
final ExecutorService experimentExecutor = Executors.newSingleThreadExecutor();
|
final ExecutorService experimentExecutor = Executors.newSingleThreadExecutor();
|
||||||
|
|
||||||
experiment.compareSupplierResultAsync(12, () -> 12, experimentExecutor);
|
experiment.compareSupplierResultAsync(12, () -> 12, experimentExecutor);
|
||||||
experimentExecutor.shutdown();
|
experimentExecutor.shutdown();
|
||||||
experimentExecutor.awaitTermination(1, TimeUnit.SECONDS);
|
experimentExecutor.awaitTermination(1, TimeUnit.SECONDS);
|
||||||
|
|
||||||
verify(matchTimer).record(anyLong(), eq(TimeUnit.NANOSECONDS));
|
verify(matchTimer).record(anyLong(), eq(TimeUnit.NANOSECONDS));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void compareSupplierResultAsyncError() throws InterruptedException {
|
void compareSupplierResultAsyncError() throws InterruptedException {
|
||||||
final ExecutorService experimentExecutor = Executors.newSingleThreadExecutor();
|
final ExecutorService experimentExecutor = Executors.newSingleThreadExecutor();
|
||||||
|
|
||||||
experiment.compareSupplierResultAsync(12, () -> { throw new RuntimeException("OH NO"); }, experimentExecutor);
|
experiment.compareSupplierResultAsync(12, () -> {
|
||||||
experimentExecutor.shutdown();
|
throw new RuntimeException("OH NO");
|
||||||
experimentExecutor.awaitTermination(1, TimeUnit.SECONDS);
|
}, experimentExecutor);
|
||||||
|
experimentExecutor.shutdown();
|
||||||
|
experimentExecutor.awaitTermination(1, TimeUnit.SECONDS);
|
||||||
|
|
||||||
verify(errorTimer).record(anyLong(), eq(TimeUnit.NANOSECONDS));
|
verify(errorTimer).record(anyLong(), eq(TimeUnit.NANOSECONDS));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void compareSupplierResultAsyncRejection() {
|
void compareSupplierResultAsyncRejection() {
|
||||||
final ExecutorService executorService = mock(ExecutorService.class);
|
final ExecutorService executorService = mock(ExecutorService.class);
|
||||||
doThrow(new RejectedExecutionException()).when(executorService).execute(any(Runnable.class));
|
doThrow(new RejectedExecutionException()).when(executorService).execute(any(Runnable.class));
|
||||||
|
|
||||||
experiment.compareSupplierResultAsync(12, () -> 12, executorService);
|
experiment.compareSupplierResultAsync(12, () -> 12, executorService);
|
||||||
verify(errorTimer).record(anyLong(), eq(TimeUnit.NANOSECONDS));
|
verify(errorTimer).record(anyLong(), eq(TimeUnit.NANOSECONDS));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ParameterizedTest
|
@ParameterizedTest
|
||||||
@MethodSource("argumentsForTestRecordResult")
|
@MethodSource
|
||||||
public void testRecordResult(final Object expected, final Object actual, final Experiment experiment, final Timer expectedTimer) {
|
public void testRecordResult(final Object expected, final Object actual, final Experiment experiment,
|
||||||
reset(expectedTimer);
|
final Timer expectedTimer) {
|
||||||
|
reset(expectedTimer);
|
||||||
|
|
||||||
final long durationNanos = 123;
|
final long durationNanos = 123;
|
||||||
|
|
||||||
experiment.recordResult(expected, actual, durationNanos);
|
experiment.recordResult(expected, actual, durationNanos);
|
||||||
verify(expectedTimer).record(durationNanos, TimeUnit.NANOSECONDS);
|
verify(expectedTimer).record(durationNanos, TimeUnit.NANOSECONDS);
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unused")
|
@SuppressWarnings("unused")
|
||||||
private static Object[] argumentsForTestRecordResult() {
|
private static Stream<Arguments> testRecordResult() {
|
||||||
// Hack: parameters are set before the @Before method gets called
|
// Hack: parameters are set before the @Before method gets called
|
||||||
final Timer matchTimer = mock(Timer.class);
|
final Timer matchTimer = mock(Timer.class);
|
||||||
final Timer errorTimer = mock(Timer.class);
|
final Timer errorTimer = mock(Timer.class);
|
||||||
final Timer bothPresentMismatchTimer = mock(Timer.class);
|
final Timer bothPresentMismatchTimer = mock(Timer.class);
|
||||||
final Timer controlNullMismatchTimer = mock(Timer.class);
|
final Timer controlNullMismatchTimer = mock(Timer.class);
|
||||||
final Timer experimentNullMismatchTimer = mock(Timer.class);
|
final Timer experimentNullMismatchTimer = mock(Timer.class);
|
||||||
|
|
||||||
final Experiment experiment = new Experiment("test", matchTimer, errorTimer, bothPresentMismatchTimer, controlNullMismatchTimer, experimentNullMismatchTimer);
|
final Experiment experiment = new Experiment("test", matchTimer, errorTimer, bothPresentMismatchTimer,
|
||||||
|
controlNullMismatchTimer, experimentNullMismatchTimer);
|
||||||
|
|
||||||
return new Object[] {
|
return Stream.of(
|
||||||
new Object[] { 12, 12, experiment, matchTimer },
|
Arguments.of(12, 12, experiment, matchTimer),
|
||||||
new Object[] { null, 12, experiment, controlNullMismatchTimer },
|
Arguments.of(null, 12, experiment, controlNullMismatchTimer),
|
||||||
new Object[] { 12, null, experiment, experimentNullMismatchTimer },
|
Arguments.of(12, null, experiment, experimentNullMismatchTimer),
|
||||||
new Object[] { 12, 17, experiment, bothPresentMismatchTimer },
|
Arguments.of(12, 17, experiment, bothPresentMismatchTimer),
|
||||||
new Object[] { Optional.of(12), Optional.of(12), experiment, matchTimer },
|
Arguments.of(Optional.of(12), Optional.of(12), experiment, matchTimer),
|
||||||
new Object[] { Optional.empty(), Optional.of(12), experiment, controlNullMismatchTimer },
|
Arguments.of(Optional.empty(), Optional.of(12), experiment, controlNullMismatchTimer),
|
||||||
new Object[] { Optional.of(12), Optional.empty(), experiment, experimentNullMismatchTimer },
|
Arguments.of(Optional.of(12), Optional.empty(), experiment, experimentNullMismatchTimer),
|
||||||
new Object[] { Optional.of(12), Optional.of(17), experiment, bothPresentMismatchTimer }
|
Arguments.of(Optional.of(12), Optional.of(17), experiment, bothPresentMismatchTimer)
|
||||||
};
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2013-2021 Signal Messenger, LLC
|
* Copyright 2013-2022 Signal Messenger, LLC
|
||||||
* SPDX-License-Identifier: AGPL-3.0-only
|
* SPDX-License-Identifier: AGPL-3.0-only
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -8,81 +8,84 @@ package org.whispersystems.textsecuregcm.metrics;
|
||||||
|
|
||||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
|
||||||
|
import java.util.stream.Stream;
|
||||||
import org.junit.jupiter.params.ParameterizedTest;
|
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.MethodSource;
|
||||||
|
|
||||||
class OperatingSystemMemoryGaugeTest {
|
class OperatingSystemMemoryGaugeTest {
|
||||||
|
|
||||||
private static final String MEMINFO =
|
private static final String MEMINFO =
|
||||||
"""
|
"""
|
||||||
MemTotal: 16052208 kB
|
MemTotal: 16052208 kB
|
||||||
MemFree: 4568468 kB
|
MemFree: 4568468 kB
|
||||||
MemAvailable: 7702848 kB
|
MemAvailable: 7702848 kB
|
||||||
Buffers: 636372 kB
|
Buffers: 636372 kB
|
||||||
Cached: 5019116 kB
|
Cached: 5019116 kB
|
||||||
SwapCached: 6692 kB
|
SwapCached: 6692 kB
|
||||||
Active: 7746436 kB
|
Active: 7746436 kB
|
||||||
Inactive: 2729876 kB
|
Inactive: 2729876 kB
|
||||||
Active(anon): 5580980 kB
|
Active(anon): 5580980 kB
|
||||||
Inactive(anon): 1648108 kB
|
Inactive(anon): 1648108 kB
|
||||||
Active(file): 2165456 kB
|
Active(file): 2165456 kB
|
||||||
Inactive(file): 1081768 kB
|
Inactive(file): 1081768 kB
|
||||||
Unevictable: 443948 kB
|
Unevictable: 443948 kB
|
||||||
Mlocked: 4924 kB
|
Mlocked: 4924 kB
|
||||||
SwapTotal: 1003516 kB
|
SwapTotal: 1003516 kB
|
||||||
SwapFree: 935932 kB
|
SwapFree: 935932 kB
|
||||||
Dirty: 28308 kB
|
Dirty: 28308 kB
|
||||||
Writeback: 0 kB
|
Writeback: 0 kB
|
||||||
AnonPages: 5258396 kB
|
AnonPages: 5258396 kB
|
||||||
Mapped: 1530740 kB
|
Mapped: 1530740 kB
|
||||||
Shmem: 2419340 kB
|
Shmem: 2419340 kB
|
||||||
KReclaimable: 229392 kB
|
KReclaimable: 229392 kB
|
||||||
Slab: 408156 kB
|
Slab: 408156 kB
|
||||||
SReclaimable: 229392 kB
|
SReclaimable: 229392 kB
|
||||||
SUnreclaim: 178764 kB
|
SUnreclaim: 178764 kB
|
||||||
KernelStack: 17360 kB
|
KernelStack: 17360 kB
|
||||||
PageTables: 50436 kB
|
PageTables: 50436 kB
|
||||||
NFS_Unstable: 0 kB
|
NFS_Unstable: 0 kB
|
||||||
Bounce: 0 kB
|
Bounce: 0 kB
|
||||||
WritebackTmp: 0 kB
|
WritebackTmp: 0 kB
|
||||||
CommitLimit: 9029620 kB
|
CommitLimit: 9029620 kB
|
||||||
Committed_AS: 16681884 kB
|
Committed_AS: 16681884 kB
|
||||||
VmallocTotal: 34359738367 kB
|
VmallocTotal: 34359738367 kB
|
||||||
VmallocUsed: 41944 kB
|
VmallocUsed: 41944 kB
|
||||||
VmallocChunk: 0 kB
|
VmallocChunk: 0 kB
|
||||||
Percpu: 4240 kB
|
Percpu: 4240 kB
|
||||||
HardwareCorrupted: 0 kB
|
HardwareCorrupted: 0 kB
|
||||||
AnonHugePages: 0 kB
|
AnonHugePages: 0 kB
|
||||||
ShmemHugePages: 0 kB
|
ShmemHugePages: 0 kB
|
||||||
ShmemPmdMapped: 0 kB
|
ShmemPmdMapped: 0 kB
|
||||||
FileHugePages: 0 kB
|
FileHugePages: 0 kB
|
||||||
FilePmdMapped: 0 kB
|
FilePmdMapped: 0 kB
|
||||||
CmaTotal: 0 kB
|
CmaTotal: 0 kB
|
||||||
CmaFree: 0 kB
|
CmaFree: 0 kB
|
||||||
HugePages_Total: 0
|
HugePages_Total: 0
|
||||||
HugePages_Free: 7
|
HugePages_Free: 7
|
||||||
HugePages_Rsvd: 0
|
HugePages_Rsvd: 0
|
||||||
HugePages_Surp: 0
|
HugePages_Surp: 0
|
||||||
Hugepagesize: 2048 kB
|
Hugepagesize: 2048 kB
|
||||||
Hugetlb: 0 kB
|
Hugetlb: 0 kB
|
||||||
DirectMap4k: 481804 kB
|
DirectMap4k: 481804 kB
|
||||||
DirectMap2M: 14901248 kB
|
DirectMap2M: 14901248 kB
|
||||||
DirectMap1G: 2097152 kB
|
DirectMap1G: 2097152 kB
|
||||||
""";
|
""";
|
||||||
|
|
||||||
@ParameterizedTest
|
@ParameterizedTest
|
||||||
@MethodSource("argumentsForTestGetValue")
|
@MethodSource
|
||||||
public void testGetValue(final String metricName, final long expectedValue) {
|
void testGetValue(final String metricName, final long expectedValue) {
|
||||||
assertEquals(expectedValue, new OperatingSystemMemoryGauge(metricName).getValue(MEMINFO.lines()));
|
assertEquals(expectedValue, new OperatingSystemMemoryGauge(metricName).getValue(MEMINFO.lines()));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Object[] argumentsForTestGetValue() {
|
@SuppressWarnings("unused")
|
||||||
return new Object[] {
|
private static Stream<Arguments> testGetValue() {
|
||||||
new Object[] { "MemTotal", 16052208L },
|
return Stream.of(
|
||||||
new Object[] { "Active(anon)", 5580980L },
|
Arguments.of("MemTotal", 16052208L),
|
||||||
new Object[] { "Committed_AS", 16681884L },
|
Arguments.of("Active(anon)", 5580980L),
|
||||||
new Object[] { "HugePages_Free", 7L },
|
Arguments.of("Committed_AS", 16681884L),
|
||||||
new Object[] { "NonsenseMetric", 0L }
|
Arguments.of("HugePages_Free", 7L),
|
||||||
};
|
Arguments.of("NonsenseMetric", 0L)
|
||||||
}
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2013-2020 Signal Messenger, LLC
|
* Copyright 2013-2022 Signal Messenger, LLC
|
||||||
* SPDX-License-Identifier: AGPL-3.0-only
|
* SPDX-License-Identifier: AGPL-3.0-only
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -11,81 +11,85 @@ import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||||
import io.micrometer.core.instrument.Tag;
|
import io.micrometer.core.instrument.Tag;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.stream.Stream;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.junit.jupiter.params.ParameterizedTest;
|
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.MethodSource;
|
||||||
|
|
||||||
class UserAgentTagUtilTest {
|
class UserAgentTagUtilTest {
|
||||||
|
|
||||||
@ParameterizedTest
|
@ParameterizedTest
|
||||||
@MethodSource("argumentsForTestGetUserAgentTags")
|
@MethodSource
|
||||||
public void testGetUserAgentTags(final String userAgent, final List<Tag> expectedTags) {
|
public void testGetUserAgentTags(final String userAgent, final List<Tag> expectedTags) {
|
||||||
assertEquals(new HashSet<>(expectedTags),
|
assertEquals(new HashSet<>(expectedTags),
|
||||||
new HashSet<>(UserAgentTagUtil.getUserAgentTags(userAgent)));
|
new HashSet<>(UserAgentTagUtil.getUserAgentTags(userAgent)));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static List<Tag> platformVersionTags(String platform, String version) {
|
||||||
|
return List.of(Tag.of(UserAgentTagUtil.PLATFORM_TAG, platform), Tag.of(UserAgentTagUtil.VERSION_TAG, version));
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unused")
|
||||||
|
private static Stream<Arguments> testGetUserAgentTags() {
|
||||||
|
return Stream.of(
|
||||||
|
Arguments.of("This is obviously not a reasonable User-Agent string.", UserAgentTagUtil.UNRECOGNIZED_TAGS),
|
||||||
|
Arguments.of(null, UserAgentTagUtil.UNRECOGNIZED_TAGS),
|
||||||
|
Arguments.of("Signal-Android 4.53.7 (Android 8.1)", platformVersionTags("android", "4.53.7")),
|
||||||
|
Arguments.of("Signal Desktop 1.2.3", platformVersionTags("desktop", "1.2.3")),
|
||||||
|
Arguments.of("Signal/3.9.0 (iPhone; iOS 12.2; Scale/3.00)", platformVersionTags("ios", "3.9.0")),
|
||||||
|
Arguments.of("Signal-Android 1.2.3 (Android 8.1)", UserAgentTagUtil.UNRECOGNIZED_TAGS),
|
||||||
|
Arguments.of("Signal Desktop 3.9.0", platformVersionTags("desktop", "3.9.0")),
|
||||||
|
Arguments.of("Signal/4.53.7 (iPhone; iOS 12.2; Scale/3.00)", platformVersionTags("ios", "4.53.7")),
|
||||||
|
Arguments.of("Signal-Android 4.68.3 (Android 9)", platformVersionTags("android", "4.68.3")),
|
||||||
|
Arguments.of("Signal-Android 1.2.3 (Android 4.3)", UserAgentTagUtil.UNRECOGNIZED_TAGS),
|
||||||
|
Arguments.of("Signal-Android 4.68.3.0-bobsbootlegclient", UserAgentTagUtil.UNRECOGNIZED_TAGS),
|
||||||
|
Arguments.of("Signal Desktop 1.22.45-foo-0", UserAgentTagUtil.UNRECOGNIZED_TAGS),
|
||||||
|
Arguments.of("Signal Desktop 1.34.5-beta.1-fakeclientemporium", UserAgentTagUtil.UNRECOGNIZED_TAGS),
|
||||||
|
Arguments.of("Signal Desktop 1.32.0-beta.3", UserAgentTagUtil.UNRECOGNIZED_TAGS)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testGetUserAgentTagsFlooded() {
|
||||||
|
for (int i = 0; i < UserAgentTagUtil.MAX_VERSIONS; i++) {
|
||||||
|
UserAgentTagUtil.getUserAgentTags(String.format("Signal-Android 4.0.%d (Android 8.1)", i));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static List<Tag> platformVersionTags(String platform, String version) {
|
assertEquals(UserAgentTagUtil.OVERFLOW_TAGS,
|
||||||
return List.of(Tag.of(UserAgentTagUtil.PLATFORM_TAG, platform), Tag.of(UserAgentTagUtil.VERSION_TAG, version));
|
UserAgentTagUtil.getUserAgentTags("Signal-Android 4.1.0 (Android 8.1)"));
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("unused")
|
final List<Tag> tags = UserAgentTagUtil.getUserAgentTags("Signal-Android 4.0.0 (Android 8.1)");
|
||||||
private static Object[] argumentsForTestGetUserAgentTags() {
|
|
||||||
return new Object[] {
|
|
||||||
new Object[] { "This is obviously not a reasonable User-Agent string.", UserAgentTagUtil.UNRECOGNIZED_TAGS },
|
|
||||||
new Object[] { null, UserAgentTagUtil.UNRECOGNIZED_TAGS },
|
|
||||||
new Object[] { "Signal-Android 4.53.7 (Android 8.1)", platformVersionTags("android", "4.53.7") },
|
|
||||||
new Object[] { "Signal Desktop 1.2.3", platformVersionTags("desktop", "1.2.3") },
|
|
||||||
new Object[] { "Signal/3.9.0 (iPhone; iOS 12.2; Scale/3.00)", platformVersionTags("ios", "3.9.0") },
|
|
||||||
new Object[] { "Signal-Android 1.2.3 (Android 8.1)", UserAgentTagUtil.UNRECOGNIZED_TAGS },
|
|
||||||
new Object[] { "Signal Desktop 3.9.0", platformVersionTags("desktop", "3.9.0") },
|
|
||||||
new Object[] { "Signal/4.53.7 (iPhone; iOS 12.2; Scale/3.00)", platformVersionTags("ios", "4.53.7") },
|
|
||||||
new Object[] { "Signal-Android 4.68.3 (Android 9)", platformVersionTags("android", "4.68.3") },
|
|
||||||
new Object[] { "Signal-Android 1.2.3 (Android 4.3)", UserAgentTagUtil.UNRECOGNIZED_TAGS },
|
|
||||||
new Object[] { "Signal-Android 4.68.3.0-bobsbootlegclient", UserAgentTagUtil.UNRECOGNIZED_TAGS },
|
|
||||||
new Object[] { "Signal Desktop 1.22.45-foo-0", UserAgentTagUtil.UNRECOGNIZED_TAGS },
|
|
||||||
new Object[] { "Signal Desktop 1.34.5-beta.1-fakeclientemporium", UserAgentTagUtil.UNRECOGNIZED_TAGS },
|
|
||||||
new Object[] { "Signal Desktop 1.32.0-beta.3", UserAgentTagUtil.UNRECOGNIZED_TAGS },
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
assertEquals(2, tags.size());
|
||||||
void testGetUserAgentTagsFlooded() {
|
assertTrue(tags.contains(Tag.of(UserAgentTagUtil.PLATFORM_TAG, "android")));
|
||||||
for (int i = 0; i < UserAgentTagUtil.MAX_VERSIONS; i++) {
|
assertTrue(tags.contains(Tag.of(UserAgentTagUtil.VERSION_TAG, "4.0.0")));
|
||||||
UserAgentTagUtil.getUserAgentTags(String.format("Signal-Android 4.0.%d (Android 8.1)", i));
|
}
|
||||||
}
|
|
||||||
|
|
||||||
assertEquals(UserAgentTagUtil.OVERFLOW_TAGS,
|
@ParameterizedTest
|
||||||
UserAgentTagUtil.getUserAgentTags("Signal-Android 4.1.0 (Android 8.1)"));
|
@MethodSource("argumentsForTestGetPlatformTag")
|
||||||
|
public void testGetPlatformTag(final String userAgent, final Tag expectedTag) {
|
||||||
|
assertEquals(expectedTag, UserAgentTagUtil.getPlatformTag(userAgent));
|
||||||
|
}
|
||||||
|
|
||||||
final List<Tag> tags = UserAgentTagUtil.getUserAgentTags("Signal-Android 4.0.0 (Android 8.1)");
|
private static Stream<Arguments> argumentsForTestGetPlatformTag() {
|
||||||
|
return Stream.of(
|
||||||
assertEquals(2, tags.size());
|
Arguments.of("This is obviously not a reasonable User-Agent string.",
|
||||||
assertTrue(tags.contains(Tag.of(UserAgentTagUtil.PLATFORM_TAG, "android")));
|
Tag.of(UserAgentTagUtil.PLATFORM_TAG, "unrecognized")),
|
||||||
assertTrue(tags.contains(Tag.of(UserAgentTagUtil.VERSION_TAG, "4.0.0")));
|
Arguments.of(null, Tag.of(UserAgentTagUtil.PLATFORM_TAG, "unrecognized")),
|
||||||
}
|
Arguments.of("Signal-Android 4.53.7 (Android 8.1)", Tag.of(UserAgentTagUtil.PLATFORM_TAG, "android")),
|
||||||
|
Arguments.of("Signal Desktop 1.2.3", Tag.of(UserAgentTagUtil.PLATFORM_TAG, "desktop")),
|
||||||
@ParameterizedTest
|
Arguments.of("Signal/3.9.0 (iPhone; iOS 12.2; Scale/3.00)", Tag.of(UserAgentTagUtil.PLATFORM_TAG, "ios")),
|
||||||
@MethodSource("argumentsForTestGetPlatformTag")
|
Arguments.of("Signal-Android 1.2.3 (Android 8.1)", Tag.of(UserAgentTagUtil.PLATFORM_TAG, "android")),
|
||||||
public void testGetPlatformTag(final String userAgent, final Tag expectedTag) {
|
Arguments.of("Signal Desktop 3.9.0", Tag.of(UserAgentTagUtil.PLATFORM_TAG, "desktop")),
|
||||||
assertEquals(expectedTag, UserAgentTagUtil.getPlatformTag(userAgent));
|
Arguments.of("Signal/4.53.7 (iPhone; iOS 12.2; Scale/3.00)", Tag.of(UserAgentTagUtil.PLATFORM_TAG, "ios")),
|
||||||
}
|
Arguments.of("Signal-Android 4.68.3 (Android 9)", Tag.of(UserAgentTagUtil.PLATFORM_TAG, "android")),
|
||||||
|
Arguments.of("Signal-Android 1.2.3 (Android 4.3)", Tag.of(UserAgentTagUtil.PLATFORM_TAG, "android")),
|
||||||
private static Object[] argumentsForTestGetPlatformTag() {
|
Arguments.of("Signal-Android 4.68.3.0-bobsbootlegclient", Tag.of(UserAgentTagUtil.PLATFORM_TAG, "android")),
|
||||||
return new Object[] {
|
Arguments.of("Signal Desktop 1.22.45-foo-0", Tag.of(UserAgentTagUtil.PLATFORM_TAG, "desktop")),
|
||||||
new Object[] { "This is obviously not a reasonable User-Agent string.", Tag.of(UserAgentTagUtil.PLATFORM_TAG, "unrecognized") },
|
Arguments.of("Signal Desktop 1.34.5-beta.1-fakeclientemporium",
|
||||||
new Object[] { null, Tag.of(UserAgentTagUtil.PLATFORM_TAG, "unrecognized") },
|
Tag.of(UserAgentTagUtil.PLATFORM_TAG, "desktop")),
|
||||||
new Object[] { "Signal-Android 4.53.7 (Android 8.1)", Tag.of(UserAgentTagUtil.PLATFORM_TAG, "android") },
|
Arguments.of("Signal Desktop 1.32.0-beta.3", Tag.of(UserAgentTagUtil.PLATFORM_TAG, "desktop"))
|
||||||
new Object[] { "Signal Desktop 1.2.3", Tag.of(UserAgentTagUtil.PLATFORM_TAG, "desktop") },
|
);
|
||||||
new Object[] { "Signal/3.9.0 (iPhone; iOS 12.2; Scale/3.00)", Tag.of(UserAgentTagUtil.PLATFORM_TAG, "ios") },
|
}
|
||||||
new Object[] { "Signal-Android 1.2.3 (Android 8.1)", Tag.of(UserAgentTagUtil.PLATFORM_TAG, "android") },
|
|
||||||
new Object[] { "Signal Desktop 3.9.0", Tag.of(UserAgentTagUtil.PLATFORM_TAG, "desktop") },
|
|
||||||
new Object[] { "Signal/4.53.7 (iPhone; iOS 12.2; Scale/3.00)", Tag.of(UserAgentTagUtil.PLATFORM_TAG, "ios") },
|
|
||||||
new Object[] { "Signal-Android 4.68.3 (Android 9)", Tag.of(UserAgentTagUtil.PLATFORM_TAG, "android") },
|
|
||||||
new Object[] { "Signal-Android 1.2.3 (Android 4.3)", Tag.of(UserAgentTagUtil.PLATFORM_TAG, "android") },
|
|
||||||
new Object[] { "Signal-Android 4.68.3.0-bobsbootlegclient", Tag.of(UserAgentTagUtil.PLATFORM_TAG, "android") },
|
|
||||||
new Object[] { "Signal Desktop 1.22.45-foo-0", Tag.of(UserAgentTagUtil.PLATFORM_TAG, "desktop") },
|
|
||||||
new Object[] { "Signal Desktop 1.34.5-beta.1-fakeclientemporium", Tag.of(UserAgentTagUtil.PLATFORM_TAG, "desktop") },
|
|
||||||
new Object[] { "Signal Desktop 1.32.0-beta.3", Tag.of(UserAgentTagUtil.PLATFORM_TAG, "desktop") },
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,8 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2021-2022 Signal Messenger, LLC
|
||||||
|
* SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
*/
|
||||||
|
|
||||||
package org.whispersystems.textsecuregcm.sms;
|
package org.whispersystems.textsecuregcm.sms;
|
||||||
|
|
||||||
import static com.github.tomakehurst.wiremock.client.WireMock.aResponse;
|
import static com.github.tomakehurst.wiremock.client.WireMock.aResponse;
|
||||||
|
@ -6,7 +11,7 @@ import static com.github.tomakehurst.wiremock.client.WireMock.post;
|
||||||
import static com.github.tomakehurst.wiremock.client.WireMock.postRequestedFor;
|
import static com.github.tomakehurst.wiremock.client.WireMock.postRequestedFor;
|
||||||
import static com.github.tomakehurst.wiremock.client.WireMock.urlEqualTo;
|
import static com.github.tomakehurst.wiremock.client.WireMock.urlEqualTo;
|
||||||
import static com.github.tomakehurst.wiremock.core.WireMockConfiguration.wireMockConfig;
|
import static com.github.tomakehurst.wiremock.core.WireMockConfiguration.wireMockConfig;
|
||||||
import static org.assertj.core.api.AssertionsForClassTypes.assertThat;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
|
||||||
import com.github.tomakehurst.wiremock.junit5.WireMockExtension;
|
import com.github.tomakehurst.wiremock.junit5.WireMockExtension;
|
||||||
|
@ -16,11 +21,13 @@ import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Locale.LanguageRange;
|
import java.util.Locale.LanguageRange;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
import java.util.stream.Stream;
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
import org.junit.jupiter.api.BeforeEach;
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.junit.jupiter.api.extension.RegisterExtension;
|
import org.junit.jupiter.api.extension.RegisterExtension;
|
||||||
import org.junit.jupiter.params.ParameterizedTest;
|
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.MethodSource;
|
||||||
import org.whispersystems.textsecuregcm.configuration.TwilioConfiguration;
|
import org.whispersystems.textsecuregcm.configuration.TwilioConfiguration;
|
||||||
import org.whispersystems.textsecuregcm.http.FaultTolerantHttpClient;
|
import org.whispersystems.textsecuregcm.http.FaultTolerantHttpClient;
|
||||||
|
@ -89,7 +96,7 @@ class TwilioVerifySenderTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
@ParameterizedTest
|
@ParameterizedTest
|
||||||
@MethodSource("argumentsForDeliverSmsVerificationWithVerify")
|
@MethodSource
|
||||||
void deliverSmsVerificationWithVerify(@Nullable final String client, @Nullable final String languageRange,
|
void deliverSmsVerificationWithVerify(@Nullable final String client, @Nullable final String languageRange,
|
||||||
final boolean expectAppHash, @Nullable final String expectedLocale) throws Exception {
|
final boolean expectAppHash, @Nullable final String expectedLocale) throws Exception {
|
||||||
|
|
||||||
|
@ -114,17 +121,18 @@ class TwilioVerifySenderTest {
|
||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Object[] argumentsForDeliverSmsVerificationWithVerify() {
|
@SuppressWarnings("unused")
|
||||||
return new Object[][]{
|
private static Stream<Arguments> deliverSmsVerificationWithVerify() {
|
||||||
|
return Stream.of(
|
||||||
// client, languageRange, expectAppHash, expectedLocale
|
// client, languageRange, expectAppHash, expectedLocale
|
||||||
{"ios", "fr-CA, en", false, "fr"},
|
Arguments.of("ios", "fr-CA, en", false, "fr"),
|
||||||
{"android-2021-03", "zh-HK, it", true, "zh-HK"},
|
Arguments.of("android-2021-03", "zh-HK, it", true, "zh-HK"),
|
||||||
{null, null, false, null}
|
Arguments.of(null, null, false, null)
|
||||||
};
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ParameterizedTest
|
@ParameterizedTest
|
||||||
@MethodSource("argumentsForDeliverVoxVerificationWithVerify")
|
@MethodSource
|
||||||
void deliverVoxVerificationWithVerify(@Nullable final String languageRange,
|
void deliverVoxVerificationWithVerify(@Nullable final String languageRange,
|
||||||
@Nullable final String expectedLocale) throws Exception {
|
@Nullable final String expectedLocale) throws Exception {
|
||||||
|
|
||||||
|
@ -147,14 +155,15 @@ class TwilioVerifySenderTest {
|
||||||
+ "&CustomCode=123456")));
|
+ "&CustomCode=123456")));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Object[] argumentsForDeliverVoxVerificationWithVerify() {
|
@SuppressWarnings("unused")
|
||||||
return new Object[][]{
|
private static Stream<Arguments> deliverVoxVerificationWithVerify() {
|
||||||
|
return Stream.of(
|
||||||
// languageRange, expectedLocale
|
// languageRange, expectedLocale
|
||||||
{"fr-CA, en", "fr"},
|
Arguments.of("fr-CA, en", "fr"),
|
||||||
{"zh-HK, it", "zh-HK"},
|
Arguments.of("zh-HK, it", "zh-HK"),
|
||||||
{"en-CAA, en", "en"},
|
Arguments.of("en-CAA, en", "en"),
|
||||||
{null, null}
|
Arguments.of(null, null)
|
||||||
};
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -203,16 +212,17 @@ class TwilioVerifySenderTest {
|
||||||
wireMock.stubFor(post(urlEqualTo("/v2/Services/" + VERIFY_SERVICE_SID + "/Verifications/" + VERIFICATION_SID))
|
wireMock.stubFor(post(urlEqualTo("/v2/Services/" + VERIFY_SERVICE_SID + "/Verifications/" + VERIFICATION_SID))
|
||||||
.withBasicAuth(ACCOUNT_ID, ACCOUNT_TOKEN)
|
.withBasicAuth(ACCOUNT_ID, ACCOUNT_TOKEN)
|
||||||
.willReturn(aResponse()
|
.willReturn(aResponse()
|
||||||
.withStatus(200)
|
.withStatus(200)
|
||||||
.withHeader("Content-Type", "application/json")
|
.withHeader("Content-Type", "application/json")
|
||||||
.withBody("{\"status\": \"approved\", \"sid\": \"" + VERIFICATION_SID + "\"}")));
|
.withBody("{\"status\": \"approved\", \"sid\": \"" + VERIFICATION_SID + "\"}")));
|
||||||
|
|
||||||
final Boolean success = sender.reportVerificationSucceeded(VERIFICATION_SID).get();
|
final Boolean success = sender.reportVerificationSucceeded(VERIFICATION_SID).get();
|
||||||
|
|
||||||
assertThat(success).isTrue();
|
assertThat(success).isTrue();
|
||||||
|
|
||||||
wireMock.verify(1, postRequestedFor(urlEqualTo("/v2/Services/" + VERIFY_SERVICE_SID + "/Verifications/" + VERIFICATION_SID))
|
wireMock.verify(1,
|
||||||
.withHeader("Content-Type", equalTo("application/x-www-form-urlencoded"))
|
postRequestedFor(urlEqualTo("/v2/Services/" + VERIFY_SERVICE_SID + "/Verifications/" + VERIFICATION_SID))
|
||||||
.withRequestBody(equalTo("Status=approved")));
|
.withHeader("Content-Type", equalTo("application/x-www-form-urlencoded"))
|
||||||
|
.withRequestBody(equalTo("Status=approved")));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2013-2020 Signal Messenger, LLC
|
* Copyright 2013-2022 Signal Messenger, LLC
|
||||||
* SPDX-License-Identifier: AGPL-3.0-only
|
* SPDX-License-Identifier: AGPL-3.0-only
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -9,113 +9,119 @@ import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
import static org.mockito.Mockito.mock;
|
import static org.mockito.Mockito.mock;
|
||||||
|
|
||||||
import java.time.Duration;
|
import java.time.Duration;
|
||||||
|
import java.util.stream.Stream;
|
||||||
import org.junit.jupiter.params.ParameterizedTest;
|
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.MethodSource;
|
||||||
import org.whispersystems.textsecuregcm.entities.SignedPreKey;
|
import org.whispersystems.textsecuregcm.entities.SignedPreKey;
|
||||||
|
|
||||||
class DeviceTest {
|
class DeviceTest {
|
||||||
|
|
||||||
@ParameterizedTest
|
@ParameterizedTest
|
||||||
@MethodSource("argumentsForTestIsEnabled")
|
@MethodSource
|
||||||
void testIsEnabled(final boolean master, final boolean fetchesMessages, final String apnId, final String gcmId, final SignedPreKey signedPreKey, final Duration timeSinceLastSeen, final boolean expectEnabled) {
|
void testIsEnabled(final boolean master, final boolean fetchesMessages, final String apnId, final String gcmId,
|
||||||
final long lastSeen = System.currentTimeMillis() - timeSinceLastSeen.toMillis();
|
final SignedPreKey signedPreKey, final Duration timeSinceLastSeen, final boolean expectEnabled) {
|
||||||
final Device device = new Device(master ? 1 : 2, "test", "auth-token", "salt", gcmId, apnId, null, fetchesMessages, 1, signedPreKey, lastSeen, lastSeen, "user-agent", 0, null);
|
final long lastSeen = System.currentTimeMillis() - timeSinceLastSeen.toMillis();
|
||||||
|
final Device device = new Device(master ? 1 : 2, "test", "auth-token", "salt", gcmId, apnId, null, fetchesMessages,
|
||||||
|
1, signedPreKey, lastSeen, lastSeen, "user-agent", 0, null);
|
||||||
|
|
||||||
assertEquals(expectEnabled, device.isEnabled());
|
assertEquals(expectEnabled, device.isEnabled());
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Object[] argumentsForTestIsEnabled() {
|
private static Stream<Arguments> testIsEnabled() {
|
||||||
return new Object[] {
|
return Stream.of(
|
||||||
// master fetchesMessages apnId gcmId signedPreKey lastSeen expectEnabled
|
// master fetchesMessages apnId gcmId signedPreKey lastSeen expectEnabled
|
||||||
new Object[] { true, false, null, null, null, Duration.ofDays(60), false },
|
Arguments.of(true, false, null, null, null, Duration.ofDays(60), false),
|
||||||
new Object[] { true, false, null, null, null, Duration.ofDays(1), false },
|
Arguments.of(true, false, null, null, null, Duration.ofDays(1), false),
|
||||||
new Object[] { true, false, null, null, mock(SignedPreKey.class), Duration.ofDays(60), false },
|
Arguments.of(true, false, null, null, mock(SignedPreKey.class), Duration.ofDays(60), false),
|
||||||
new Object[] { true, false, null, null, mock(SignedPreKey.class), Duration.ofDays(1), false },
|
Arguments.of(true, false, null, null, mock(SignedPreKey.class), Duration.ofDays(1), false),
|
||||||
new Object[] { true, false, null, "gcm-id", null, Duration.ofDays(60), false },
|
Arguments.of(true, false, null, "gcm-id", null, Duration.ofDays(60), false),
|
||||||
new Object[] { true, false, null, "gcm-id", null, Duration.ofDays(1), false },
|
Arguments.of(true, false, null, "gcm-id", null, Duration.ofDays(1), false),
|
||||||
new Object[] { true, false, null, "gcm-id", mock(SignedPreKey.class), Duration.ofDays(60), true },
|
Arguments.of(true, false, null, "gcm-id", mock(SignedPreKey.class), Duration.ofDays(60), true),
|
||||||
new Object[] { true, false, null, "gcm-id", mock(SignedPreKey.class), Duration.ofDays(1), true },
|
Arguments.of(true, false, null, "gcm-id", mock(SignedPreKey.class), Duration.ofDays(1), true),
|
||||||
new Object[] { true, false, "apn-id", null, null, Duration.ofDays(60), false },
|
Arguments.of(true, false, "apn-id", null, null, Duration.ofDays(60), false),
|
||||||
new Object[] { true, false, "apn-id", null, null, Duration.ofDays(1), false },
|
Arguments.of(true, false, "apn-id", null, null, Duration.ofDays(1), false),
|
||||||
new Object[] { true, false, "apn-id", null, mock(SignedPreKey.class), Duration.ofDays(60), true },
|
Arguments.of(true, false, "apn-id", null, mock(SignedPreKey.class), Duration.ofDays(60), true),
|
||||||
new Object[] { true, false, "apn-id", null, mock(SignedPreKey.class), Duration.ofDays(1), true },
|
Arguments.of(true, false, "apn-id", null, mock(SignedPreKey.class), Duration.ofDays(1), true),
|
||||||
new Object[] { true, true, null, null, null, Duration.ofDays(60), false },
|
Arguments.of(true, true, null, null, null, Duration.ofDays(60), false),
|
||||||
new Object[] { true, true, null, null, null, Duration.ofDays(1), false },
|
Arguments.of(true, true, null, null, null, Duration.ofDays(1), false),
|
||||||
new Object[] { true, true, null, null, mock(SignedPreKey.class), Duration.ofDays(60), true },
|
Arguments.of(true, true, null, null, mock(SignedPreKey.class), Duration.ofDays(60), true),
|
||||||
new Object[] { true, true, null, null, mock(SignedPreKey.class), Duration.ofDays(1), true },
|
Arguments.of(true, true, null, null, mock(SignedPreKey.class), Duration.ofDays(1), true),
|
||||||
new Object[] { false, false, null, null, null, Duration.ofDays(60), false },
|
Arguments.of(false, false, null, null, null, Duration.ofDays(60), false),
|
||||||
new Object[] { false, false, null, null, null, Duration.ofDays(1), false },
|
Arguments.of(false, false, null, null, null, Duration.ofDays(1), false),
|
||||||
new Object[] { false, false, null, null, mock(SignedPreKey.class), Duration.ofDays(60), false },
|
Arguments.of(false, false, null, null, mock(SignedPreKey.class), Duration.ofDays(60), false),
|
||||||
new Object[] { false, false, null, null, mock(SignedPreKey.class), Duration.ofDays(1), false },
|
Arguments.of(false, false, null, null, mock(SignedPreKey.class), Duration.ofDays(1), false),
|
||||||
new Object[] { false, false, null, "gcm-id", null, Duration.ofDays(60), false },
|
Arguments.of(false, false, null, "gcm-id", null, Duration.ofDays(60), false),
|
||||||
new Object[] { false, false, null, "gcm-id", null, Duration.ofDays(1), false },
|
Arguments.of(false, false, null, "gcm-id", null, Duration.ofDays(1), false),
|
||||||
new Object[] { false, false, null, "gcm-id", mock(SignedPreKey.class), Duration.ofDays(60), false },
|
Arguments.of(false, false, null, "gcm-id", mock(SignedPreKey.class), Duration.ofDays(60), false),
|
||||||
new Object[] { false, false, null, "gcm-id", mock(SignedPreKey.class), Duration.ofDays(1), true },
|
Arguments.of(false, false, null, "gcm-id", mock(SignedPreKey.class), Duration.ofDays(1), true),
|
||||||
new Object[] { false, false, "apn-id", null, null, Duration.ofDays(60), false },
|
Arguments.of(false, false, "apn-id", null, null, Duration.ofDays(60), false),
|
||||||
new Object[] { false, false, "apn-id", null, null, Duration.ofDays(1), false },
|
Arguments.of(false, false, "apn-id", null, null, Duration.ofDays(1), false),
|
||||||
new Object[] { false, false, "apn-id", null, mock(SignedPreKey.class), Duration.ofDays(60), false },
|
Arguments.of(false, false, "apn-id", null, mock(SignedPreKey.class), Duration.ofDays(60), false),
|
||||||
new Object[] { false, false, "apn-id", null, mock(SignedPreKey.class), Duration.ofDays(1), true },
|
Arguments.of(false, false, "apn-id", null, mock(SignedPreKey.class), Duration.ofDays(1), true),
|
||||||
new Object[] { false, true, null, null, null, Duration.ofDays(60), false },
|
Arguments.of(false, true, null, null, null, Duration.ofDays(60), false),
|
||||||
new Object[] { false, true, null, null, null, Duration.ofDays(1), false },
|
Arguments.of(false, true, null, null, null, Duration.ofDays(1), false),
|
||||||
new Object[] { false, true, null, null, mock(SignedPreKey.class), Duration.ofDays(60), false },
|
Arguments.of(false, true, null, null, mock(SignedPreKey.class), Duration.ofDays(60), false),
|
||||||
new Object[] { false, true, null, null, mock(SignedPreKey.class), Duration.ofDays(1), true }
|
Arguments.of(false, true, null, null, mock(SignedPreKey.class), Duration.ofDays(1), true)
|
||||||
};
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ParameterizedTest
|
@ParameterizedTest
|
||||||
@MethodSource("argumentsForTestIsGroupsV2Supported")
|
@MethodSource("argumentsForTestIsGroupsV2Supported")
|
||||||
void testIsGroupsV2Supported(final boolean master, final String apnId, final boolean gv2Capability, final boolean gv2_2Capability, final boolean gv2_3Capability, final boolean expectGv2Supported) {
|
void testIsGroupsV2Supported(final boolean master, final String apnId, final boolean gv2Capability,
|
||||||
final Device.DeviceCapabilities capabilities = new Device.DeviceCapabilities(gv2Capability, gv2_2Capability, gv2_3Capability, false, false, false,
|
final boolean gv2_2Capability, final boolean gv2_3Capability, final boolean expectGv2Supported) {
|
||||||
false, false, false);
|
final Device.DeviceCapabilities capabilities = new Device.DeviceCapabilities(gv2Capability, gv2_2Capability,
|
||||||
final Device device = new Device(master ? 1 : 2, "test", "auth-token", "salt",
|
gv2_3Capability, false, false, false,
|
||||||
null, apnId, null, false, 1, null, 0, 0, "user-agent", 0, capabilities);
|
false, false, false);
|
||||||
|
final Device device = new Device(master ? 1 : 2, "test", "auth-token", "salt",
|
||||||
|
null, apnId, null, false, 1, null, 0, 0, "user-agent", 0, capabilities);
|
||||||
|
|
||||||
assertEquals(expectGv2Supported, device.isGroupsV2Supported());
|
assertEquals(expectGv2Supported, device.isGroupsV2Supported());
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Object[] argumentsForTestIsGroupsV2Supported() {
|
private static Stream<Arguments> argumentsForTestIsGroupsV2Supported() {
|
||||||
return new Object[] {
|
return Stream.of(
|
||||||
// master apnId gv2 gv2-2 gv2-3 capable
|
// master apnId gv2 gv2-2 gv2-3 capable
|
||||||
|
|
||||||
// Android master
|
// Android master
|
||||||
new Object[] { true, null, false, false, false, false },
|
Arguments.of(true, null, false, false, false, false),
|
||||||
new Object[] { true, null, true, false, false, false },
|
Arguments.of(true, null, true, false, false, false),
|
||||||
new Object[] { true, null, false, true, false, false },
|
Arguments.of(true, null, false, true, false, false),
|
||||||
new Object[] { true, null, true, true, false, false },
|
Arguments.of(true, null, true, true, false, false),
|
||||||
new Object[] { true, null, false, false, true, true },
|
Arguments.of(true, null, false, false, true, true),
|
||||||
new Object[] { true, null, true, false, true, true },
|
Arguments.of(true, null, true, false, true, true),
|
||||||
new Object[] { true, null, false, true, true, true },
|
Arguments.of(true, null, false, true, true, true),
|
||||||
new Object[] { true, null, true, true, true, true },
|
Arguments.of(true, null, true, true, true, true),
|
||||||
|
|
||||||
// iOs master
|
// iOS master
|
||||||
new Object[] { true, "apn-id", false, false, false, false },
|
Arguments.of(true, "apn-id", false, false, false, false),
|
||||||
new Object[] { true, "apn-id", true, false, false, false },
|
Arguments.of(true, "apn-id", true, false, false, false),
|
||||||
new Object[] { true, "apn-id", false, true, false, true },
|
Arguments.of(true, "apn-id", false, true, false, true),
|
||||||
new Object[] { true, "apn-id", true, true, false, true },
|
Arguments.of(true, "apn-id", true, true, false, true),
|
||||||
new Object[] { true, "apn-id", false, false, true, true },
|
Arguments.of(true, "apn-id", false, false, true, true),
|
||||||
new Object[] { true, "apn-id", true, false, true, true },
|
Arguments.of(true, "apn-id", true, false, true, true),
|
||||||
new Object[] { true, "apn-id", false, true, true, true },
|
Arguments.of(true, "apn-id", false, true, true, true),
|
||||||
new Object[] { true, "apn-id", true, true, true, true },
|
Arguments.of(true, "apn-id", true, true, true, true),
|
||||||
|
|
||||||
// iOs linked
|
// iOS linked
|
||||||
new Object[] { false, "apn-id", false, false, false, false },
|
Arguments.of(false, "apn-id", false, false, false, false),
|
||||||
new Object[] { false, "apn-id", true, false, false, false },
|
Arguments.of(false, "apn-id", true, false, false, false),
|
||||||
new Object[] { false, "apn-id", false, true, false, true },
|
Arguments.of(false, "apn-id", false, true, false, true),
|
||||||
new Object[] { false, "apn-id", true, true, false, true },
|
Arguments.of(false, "apn-id", true, true, false, true),
|
||||||
new Object[] { false, "apn-id", false, false, true, true },
|
Arguments.of(false, "apn-id", false, false, true, true),
|
||||||
new Object[] { false, "apn-id", true, false, true, true },
|
Arguments.of(false, "apn-id", true, false, true, true),
|
||||||
new Object[] { false, "apn-id", false, true, true, true },
|
Arguments.of(false, "apn-id", false, true, true, true),
|
||||||
new Object[] { false, "apn-id", true, true, true, true },
|
Arguments.of(false, "apn-id", true, true, true, true),
|
||||||
|
|
||||||
// desktop linked
|
// desktop linked
|
||||||
new Object[] { false, null, false, false, false, false },
|
Arguments.of(false, null, false, false, false, false),
|
||||||
new Object[] { false, null, true, false, false, false },
|
Arguments.of(false, null, true, false, false, false),
|
||||||
new Object[] { false, null, false, true, false, false },
|
Arguments.of(false, null, false, true, false, false),
|
||||||
new Object[] { false, null, true, true, false, false },
|
Arguments.of(false, null, true, true, false, false),
|
||||||
new Object[] { false, null, false, false, true, true },
|
Arguments.of(false, null, false, false, true, true),
|
||||||
new Object[] { false, null, true, false, true, true },
|
Arguments.of(false, null, true, false, true, true),
|
||||||
new Object[] { false, null, false, true, true, true },
|
Arguments.of(false, null, false, true, true, true),
|
||||||
new Object[] { false, null, true, true, true, true }
|
Arguments.of(false, null, true, true, true, true)
|
||||||
};
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2013-2020 Signal Messenger, LLC
|
* Copyright 2013-2022 Signal Messenger, LLC
|
||||||
* SPDX-License-Identifier: AGPL-3.0-only
|
* SPDX-License-Identifier: AGPL-3.0-only
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -9,73 +9,88 @@ import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||||
|
|
||||||
import com.vdurmont.semver4j.Semver;
|
import com.vdurmont.semver4j.Semver;
|
||||||
|
import java.util.stream.Stream;
|
||||||
import org.junit.jupiter.params.ParameterizedTest;
|
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.MethodSource;
|
||||||
|
|
||||||
class UserAgentUtilTest {
|
class UserAgentUtilTest {
|
||||||
|
|
||||||
@ParameterizedTest
|
@ParameterizedTest
|
||||||
@MethodSource("argumentsForTestParseUserAgentString")
|
@MethodSource
|
||||||
void testParseUserAgentString(final String userAgentString, final UserAgent expectedUserAgent) throws UnrecognizedUserAgentException {
|
void testParseUserAgentString(final String userAgentString, final UserAgent expectedUserAgent)
|
||||||
assertEquals(expectedUserAgent, UserAgentUtil.parseUserAgentString(userAgentString));
|
throws UnrecognizedUserAgentException {
|
||||||
}
|
assertEquals(expectedUserAgent, UserAgentUtil.parseUserAgentString(userAgentString));
|
||||||
|
}
|
||||||
|
|
||||||
private static Object[] argumentsForTestParseUserAgentString() {
|
@SuppressWarnings("unused")
|
||||||
return new Object[] {
|
private static Stream<Arguments> testParseUserAgentString() {
|
||||||
new Object[] { "Signal-Android/4.68.3 Android/25", new UserAgent(ClientPlatform.ANDROID, new Semver("4.68.3"), "Android/25") },
|
return Stream.of(
|
||||||
new Object[] { "Signal-Android 4.53.7 (Android 8.1)", new UserAgent(ClientPlatform.ANDROID, new Semver("4.53.7"), "(Android 8.1)") },
|
Arguments.of("Signal-Android/4.68.3 Android/25",
|
||||||
};
|
new UserAgent(ClientPlatform.ANDROID, new Semver("4.68.3"), "Android/25")),
|
||||||
}
|
Arguments.of("Signal-Android 4.53.7 (Android 8.1)",
|
||||||
|
new UserAgent(ClientPlatform.ANDROID, new Semver("4.53.7"), "(Android 8.1)"))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
@ParameterizedTest
|
@ParameterizedTest
|
||||||
@MethodSource("argumentsForTestParseBogusUserAgentString")
|
@MethodSource
|
||||||
void testParseBogusUserAgentString(final String userAgentString) {
|
void testParseBogusUserAgentString(final String userAgentString) {
|
||||||
assertThrows(UnrecognizedUserAgentException.class, () -> UserAgentUtil.parseUserAgentString(userAgentString));
|
assertThrows(UnrecognizedUserAgentException.class, () -> UserAgentUtil.parseUserAgentString(userAgentString));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Object[] argumentsForTestParseBogusUserAgentString() {
|
@SuppressWarnings("unused")
|
||||||
return new Object[] {
|
private static Stream<String> testParseBogusUserAgentString() {
|
||||||
null,
|
return Stream.of(
|
||||||
"This is obviously not a reasonable User-Agent string.",
|
null,
|
||||||
"Signal-Android/4.6-8.3.unreasonableversionstring-17"
|
"This is obviously not a reasonable User-Agent string.",
|
||||||
};
|
"Signal-Android/4.6-8.3.unreasonableversionstring-17"
|
||||||
}
|
);
|
||||||
|
}
|
||||||
|
|
||||||
@ParameterizedTest
|
@ParameterizedTest
|
||||||
@MethodSource("argumentsForTestParseStandardUserAgentString")
|
@MethodSource("argumentsForTestParseStandardUserAgentString")
|
||||||
void testParseStandardUserAgentString(final String userAgentString, final UserAgent expectedUserAgent) {
|
void testParseStandardUserAgentString(final String userAgentString, final UserAgent expectedUserAgent) {
|
||||||
assertEquals(expectedUserAgent, UserAgentUtil.parseStandardUserAgentString(userAgentString));
|
assertEquals(expectedUserAgent, UserAgentUtil.parseStandardUserAgentString(userAgentString));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Object[] argumentsForTestParseStandardUserAgentString() {
|
private static Stream<Arguments> argumentsForTestParseStandardUserAgentString() {
|
||||||
return new Object[] {
|
return Stream.of(
|
||||||
new Object[] { "This is obviously not a reasonable User-Agent string.", null },
|
Arguments.of("This is obviously not a reasonable User-Agent string.", null),
|
||||||
new Object[] { "Signal-Android/4.68.3 Android/25", new UserAgent(ClientPlatform.ANDROID, new Semver("4.68.3"), "Android/25") },
|
Arguments.of("Signal-Android/4.68.3 Android/25",
|
||||||
new Object[] { "Signal-Android/4.68.3", new UserAgent(ClientPlatform.ANDROID, new Semver("4.68.3")) },
|
new UserAgent(ClientPlatform.ANDROID, new Semver("4.68.3"), "Android/25")),
|
||||||
new Object[] { "Signal-Desktop/1.2.3 Linux", new UserAgent(ClientPlatform.DESKTOP, new Semver("1.2.3"), "Linux") },
|
Arguments.of("Signal-Android/4.68.3", new UserAgent(ClientPlatform.ANDROID, new Semver("4.68.3"))),
|
||||||
new Object[] { "Signal-Desktop/1.2.3 macOS", new UserAgent(ClientPlatform.DESKTOP, new Semver("1.2.3"), "macOS") },
|
Arguments.of("Signal-Desktop/1.2.3 Linux", new UserAgent(ClientPlatform.DESKTOP, new Semver("1.2.3"), "Linux")),
|
||||||
new Object[] { "Signal-Desktop/1.2.3 Windows", new UserAgent(ClientPlatform.DESKTOP, new Semver("1.2.3"), "Windows") },
|
Arguments.of("Signal-Desktop/1.2.3 macOS", new UserAgent(ClientPlatform.DESKTOP, new Semver("1.2.3"), "macOS")),
|
||||||
new Object[] { "Signal-Desktop/1.2.3", new UserAgent(ClientPlatform.DESKTOP, new Semver("1.2.3")) },
|
Arguments.of("Signal-Desktop/1.2.3 Windows",
|
||||||
new Object[] { "Signal-Desktop/1.32.0-beta.3", new UserAgent(ClientPlatform.DESKTOP, new Semver("1.32.0-beta.3")) },
|
new UserAgent(ClientPlatform.DESKTOP, new Semver("1.2.3"), "Windows")),
|
||||||
new Object[] { "Signal-iOS/3.9.0 (iPhone; iOS 12.2; Scale/3.00)", new UserAgent(ClientPlatform.IOS, new Semver("3.9.0"), "(iPhone; iOS 12.2; Scale/3.00)") },
|
Arguments.of("Signal-Desktop/1.2.3", new UserAgent(ClientPlatform.DESKTOP, new Semver("1.2.3"))),
|
||||||
new Object[] { "Signal-iOS/3.9.0 iOS/14.2", new UserAgent(ClientPlatform.IOS, new Semver("3.9.0"), "iOS/14.2") },
|
Arguments.of("Signal-Desktop/1.32.0-beta.3",
|
||||||
new Object[] { "Signal-iOS/3.9.0", new UserAgent(ClientPlatform.IOS, new Semver("3.9.0")) }
|
new UserAgent(ClientPlatform.DESKTOP, new Semver("1.32.0-beta.3"))),
|
||||||
};
|
Arguments.of("Signal-iOS/3.9.0 (iPhone; iOS 12.2; Scale/3.00)",
|
||||||
}
|
new UserAgent(ClientPlatform.IOS, new Semver("3.9.0"), "(iPhone; iOS 12.2; Scale/3.00)")),
|
||||||
|
Arguments.of("Signal-iOS/3.9.0 iOS/14.2", new UserAgent(ClientPlatform.IOS, new Semver("3.9.0"), "iOS/14.2")),
|
||||||
|
Arguments.of("Signal-iOS/3.9.0", new UserAgent(ClientPlatform.IOS, new Semver("3.9.0")))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
@ParameterizedTest
|
@ParameterizedTest
|
||||||
@MethodSource("argumentsForTestParseLegacyUserAgentString")
|
@MethodSource
|
||||||
void testParseLegacyUserAgentString(final String userAgentString, final UserAgent expectedUserAgent) {
|
void testParseLegacyUserAgentString(final String userAgentString, final UserAgent expectedUserAgent) {
|
||||||
assertEquals(expectedUserAgent, UserAgentUtil.parseLegacyUserAgentString(userAgentString));
|
assertEquals(expectedUserAgent, UserAgentUtil.parseLegacyUserAgentString(userAgentString));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Object[] argumentsForTestParseLegacyUserAgentString() {
|
@SuppressWarnings("unused")
|
||||||
return new Object[] {
|
private static Stream<Arguments> testParseLegacyUserAgentString() {
|
||||||
new Object[] { "This is obviously not a reasonable User-Agent string.", null },
|
return Stream.of(
|
||||||
new Object[] { "Signal-Android 4.53.7 (Android 8.1)", new UserAgent(ClientPlatform.ANDROID, new Semver("4.53.7"), "(Android 8.1)") },
|
Arguments.of("This is obviously not a reasonable User-Agent string.", null),
|
||||||
new Object[] { "Signal Desktop 1.2.3", new UserAgent(ClientPlatform.DESKTOP, new Semver("1.2.3")) },
|
Arguments.of("Signal-Android 4.53.7 (Android 8.1)",
|
||||||
new Object[] { "Signal Desktop 1.32.0-beta.3", new UserAgent(ClientPlatform.DESKTOP, new Semver("1.32.0-beta.3")) },
|
new UserAgent(ClientPlatform.ANDROID, new Semver("4.53.7"), "(Android 8.1)")),
|
||||||
new Object[] { "Signal/3.9.0 (iPhone; iOS 12.2; Scale/3.00)", new UserAgent(ClientPlatform.IOS, new Semver("3.9.0"), "(iPhone; iOS 12.2; Scale/3.00)") }
|
Arguments.of("Signal Desktop 1.2.3", new UserAgent(ClientPlatform.DESKTOP, new Semver("1.2.3"))),
|
||||||
};
|
Arguments.of("Signal Desktop 1.32.0-beta.3",
|
||||||
}
|
new UserAgent(ClientPlatform.DESKTOP, new Semver("1.32.0-beta.3"))),
|
||||||
|
Arguments.of("Signal/3.9.0 (iPhone; iOS 12.2; Scale/3.00)",
|
||||||
|
new UserAgent(ClientPlatform.IOS, new Semver("3.9.0"), "(iPhone; iOS 12.2; Scale/3.00)"))
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue