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