mirror of
https://github.com/signalapp/Signal-Server
synced 2026-04-20 17:08:23 +01:00
/v1/backup/auth/check endpoint added
This commit is contained in:
@@ -0,0 +1,111 @@
|
||||
/*
|
||||
* Copyright 2023 Signal Messenger, LLC
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
package org.whispersystems.textsecuregcm.util;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Set;
|
||||
import javax.validation.ConstraintViolation;
|
||||
import javax.validation.Validation;
|
||||
import javax.validation.Validator;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
public class E164Test {
|
||||
|
||||
private static final Validator VALIDATOR = Validation.buildDefaultValidatorFactory().getValidator();
|
||||
|
||||
private static final String E164_VALID = "+18005550123";
|
||||
|
||||
private static final String E164_INVALID = "1(800)555-0123";
|
||||
|
||||
private static final String EMPTY = "";
|
||||
|
||||
@SuppressWarnings("FieldCanBeLocal")
|
||||
private static class Data {
|
||||
|
||||
@E164
|
||||
private final String number;
|
||||
|
||||
private Data(final String number) {
|
||||
this.number = number;
|
||||
}
|
||||
}
|
||||
|
||||
private static class Methods {
|
||||
|
||||
public void foo(@E164 final String number) {
|
||||
// noop
|
||||
}
|
||||
|
||||
@E164
|
||||
public String bar() {
|
||||
return "nevermind";
|
||||
}
|
||||
}
|
||||
|
||||
private record Rec(@E164 String number) {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRecord() throws Exception {
|
||||
checkNoViolations(new Rec(E164_VALID));
|
||||
checkHasViolations(new Rec(E164_INVALID));
|
||||
checkHasViolations(new Rec(EMPTY));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testClassField() throws Exception {
|
||||
checkNoViolations(new Data(E164_VALID));
|
||||
checkHasViolations(new Data(E164_INVALID));
|
||||
checkHasViolations(new Data(EMPTY));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testParameters() throws Exception {
|
||||
final Methods m = new Methods();
|
||||
final Method foo = Methods.class.getMethod("foo", String.class);
|
||||
|
||||
final Set<ConstraintViolation<Methods>> violations1 =
|
||||
VALIDATOR.forExecutables().validateParameters(m, foo, new Object[] {E164_VALID});
|
||||
final Set<ConstraintViolation<Methods>> violations2 =
|
||||
VALIDATOR.forExecutables().validateParameters(m, foo, new Object[] {E164_INVALID});
|
||||
final Set<ConstraintViolation<Methods>> violations3 =
|
||||
VALIDATOR.forExecutables().validateParameters(m, foo, new Object[] {EMPTY});
|
||||
|
||||
assertTrue(violations1.isEmpty());
|
||||
assertFalse(violations2.isEmpty());
|
||||
assertFalse(violations3.isEmpty());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReturnValue() throws Exception {
|
||||
final Methods m = new Methods();
|
||||
final Method bar = Methods.class.getMethod("bar");
|
||||
|
||||
final Set<ConstraintViolation<Methods>> violations1 =
|
||||
VALIDATOR.forExecutables().validateReturnValue(m, bar, E164_VALID);
|
||||
final Set<ConstraintViolation<Methods>> violations2 =
|
||||
VALIDATOR.forExecutables().validateReturnValue(m, bar, E164_INVALID);
|
||||
final Set<ConstraintViolation<Methods>> violations3 =
|
||||
VALIDATOR.forExecutables().validateReturnValue(m, bar, EMPTY);
|
||||
|
||||
assertTrue(violations1.isEmpty());
|
||||
assertFalse(violations2.isEmpty());
|
||||
assertFalse(violations3.isEmpty());
|
||||
}
|
||||
|
||||
private static <T> void checkNoViolations(final T object) {
|
||||
final Set<ConstraintViolation<T>> violations = VALIDATOR.validate(object);
|
||||
assertTrue(violations.isEmpty());
|
||||
}
|
||||
|
||||
private static <T> void checkHasViolations(final T object) {
|
||||
final Set<ConstraintViolation<T>> violations = VALIDATOR.validate(object);
|
||||
assertFalse(violations.isEmpty());
|
||||
}
|
||||
}
|
||||
@@ -1,31 +0,0 @@
|
||||
/*
|
||||
* Copyright 2023 Signal Messenger, LLC
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
package org.whispersystems.textsecuregcm.util;
|
||||
|
||||
import org.mockito.Mockito;
|
||||
|
||||
public final class MockHelper {
|
||||
|
||||
private MockHelper() {
|
||||
// utility class
|
||||
}
|
||||
|
||||
@FunctionalInterface
|
||||
public interface MockInitializer<T> {
|
||||
|
||||
void init(T mock) throws Exception;
|
||||
}
|
||||
|
||||
public static <T> T buildMock(final Class<T> clazz, final MockInitializer<T> initializer) throws RuntimeException {
|
||||
final T mock = Mockito.mock(clazz);
|
||||
try {
|
||||
initializer.init(mock);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
return mock;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
* Copyright 2023 Signal Messenger, LLC
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
package org.whispersystems.textsecuregcm.util;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.doNothing;
|
||||
import static org.mockito.Mockito.doReturn;
|
||||
import static org.mockito.Mockito.doThrow;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.util.Optional;
|
||||
import org.mockito.Mockito;
|
||||
import org.whispersystems.textsecuregcm.controllers.RateLimitExceededException;
|
||||
import org.whispersystems.textsecuregcm.limits.RateLimiter;
|
||||
import org.whispersystems.textsecuregcm.limits.RateLimiters;
|
||||
|
||||
public final class MockUtils {
|
||||
|
||||
private MockUtils() {
|
||||
// utility class
|
||||
}
|
||||
|
||||
@FunctionalInterface
|
||||
public interface MockInitializer<T> {
|
||||
|
||||
void init(T mock) throws Exception;
|
||||
}
|
||||
|
||||
public static <T> T buildMock(final Class<T> clazz, final MockInitializer<T> initializer) throws RuntimeException {
|
||||
final T mock = Mockito.mock(clazz);
|
||||
try {
|
||||
initializer.init(mock);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
return mock;
|
||||
}
|
||||
|
||||
public static MutableClock mutableClock(final long timeMillis) {
|
||||
return new MutableClock(timeMillis);
|
||||
}
|
||||
|
||||
public static void updateRateLimiterResponseToAllow(
|
||||
final RateLimiters rateLimitersMock,
|
||||
final RateLimiters.Handle handle,
|
||||
final String input) {
|
||||
final RateLimiter mockRateLimiter = Mockito.mock(RateLimiter.class);
|
||||
doReturn(Optional.of(mockRateLimiter)).when(rateLimitersMock).byHandle(eq(handle));
|
||||
try {
|
||||
doNothing().when(mockRateLimiter).validate(eq(input));
|
||||
} catch (final RateLimitExceededException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public static void updateRateLimiterResponseToFail(
|
||||
final RateLimiters rateLimitersMock,
|
||||
final RateLimiters.Handle handle,
|
||||
final String input,
|
||||
final Duration retryAfter) {
|
||||
final RateLimiter mockRateLimiter = Mockito.mock(RateLimiter.class);
|
||||
doReturn(Optional.of(mockRateLimiter)).when(rateLimitersMock).byHandle(eq(handle));
|
||||
try {
|
||||
doThrow(new RateLimitExceededException(retryAfter)).when(mockRateLimiter).validate(eq(input));
|
||||
} catch (final RateLimitExceededException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
* Copyright 2023 Signal Messenger, LLC
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
package org.whispersystems.textsecuregcm.util;
|
||||
|
||||
import java.time.Clock;
|
||||
import java.time.Instant;
|
||||
import java.time.ZoneId;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
public class MutableClock extends Clock {
|
||||
|
||||
private final AtomicReference<Clock> delegate;
|
||||
|
||||
|
||||
public MutableClock(final long timeMillis) {
|
||||
this(fixedTimeMillis(timeMillis));
|
||||
}
|
||||
|
||||
public MutableClock(final Clock clock) {
|
||||
this.delegate = new AtomicReference<>(clock);
|
||||
}
|
||||
|
||||
public MutableClock() {
|
||||
this(Clock.systemUTC());
|
||||
}
|
||||
|
||||
public MutableClock setTimeMillis(final long timeMillis) {
|
||||
delegate.set(fixedTimeMillis(timeMillis));
|
||||
return this;
|
||||
}
|
||||
|
||||
public MutableClock incrementMillis(final long incrementMillis) {
|
||||
return increment(incrementMillis, TimeUnit.MILLISECONDS);
|
||||
}
|
||||
|
||||
public MutableClock incrementSeconds(final long incrementSeconds) {
|
||||
return increment(incrementSeconds, TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
public MutableClock increment(final long increment, final TimeUnit timeUnit) {
|
||||
final long current = delegate.get().instant().toEpochMilli();
|
||||
delegate.set(fixedTimeMillis(current + timeUnit.toMillis(increment)));
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ZoneId getZone() {
|
||||
return delegate.get().getZone();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Clock withZone(final ZoneId zone) {
|
||||
return delegate.get().withZone(zone);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Instant instant() {
|
||||
return delegate.get().instant();
|
||||
}
|
||||
|
||||
private static Clock fixedTimeMillis(final long timeMillis) {
|
||||
return Clock.fixed(Instant.ofEpochMilli(timeMillis), ZoneId.of("Etc/UTC"));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user