Remove message database from the codebase (#395)

* Remove message database from the codebase

* Remove unused ExperimentEnrollmentManager in test

* Be more stylish
This commit is contained in:
Ehren Kret
2021-02-11 10:50:03 -06:00
committed by GitHub
parent 477615fc66
commit be8a1acca9
21 changed files with 258 additions and 1049 deletions

View File

@@ -4,9 +4,25 @@
*/
package org.whispersystems.textsecuregcm.tests.controllers;
import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.Assert.assertEquals;
import static org.mockito.Mockito.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;
import static org.mockito.Mockito.when;
import com.google.common.collect.ImmutableSet;
import io.dropwizard.auth.PolymorphicAuthValueFactoryProvider;
import io.dropwizard.testing.junit.ResourceTestRule;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.TimeUnit;
import javax.ws.rs.Path;
import javax.ws.rs.client.Entity;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import junitparams.JUnitParamsRunner;
import junitparams.Parameters;
import org.glassfish.jersey.test.grizzly.GrizzlyWebTestContainerFactory;
@@ -31,23 +47,6 @@ import org.whispersystems.textsecuregcm.storage.PendingDevicesManager;
import org.whispersystems.textsecuregcm.tests.util.AuthHelper;
import org.whispersystems.textsecuregcm.util.VerificationCode;
import javax.ws.rs.Path;
import javax.ws.rs.client.Entity;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.TimeUnit;
import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.Assert.assertEquals;
import static org.mockito.Mockito.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;
import static org.mockito.Mockito.when;
@RunWith(JUnitParamsRunner.class)
public class DeviceControllerTest {
@Path("/v1/devices")
@@ -143,7 +142,7 @@ public class DeviceControllerTest {
assertThat(response.getDeviceId()).isEqualTo(42L);
verify(pendingDevicesManager).remove(AuthHelper.VALID_NUMBER);
verify(messagesManager).clear(eq(AuthHelper.VALID_NUMBER), eq(AuthHelper.VALID_UUID), eq(42L));
verify(messagesManager).clear(eq(AuthHelper.VALID_UUID), eq(42L));
}
@Test

View File

@@ -66,7 +66,6 @@ import org.whispersystems.textsecuregcm.push.ReceiptSender;
import org.whispersystems.textsecuregcm.storage.Account;
import org.whispersystems.textsecuregcm.storage.AccountsManager;
import org.whispersystems.textsecuregcm.storage.Device;
import org.whispersystems.textsecuregcm.storage.FeatureFlagsManager;
import org.whispersystems.textsecuregcm.storage.MessagesManager;
import org.whispersystems.textsecuregcm.tests.util.AuthHelper;
import org.whispersystems.textsecuregcm.util.Base64;
@@ -87,7 +86,6 @@ public class MessageControllerTest {
private final RateLimiter rateLimiter = mock(RateLimiter.class);
private final CardinalityRateLimiter unsealedSenderLimiter = mock(CardinalityRateLimiter.class);
private final ApnFallbackManager apnFallbackManager = mock(ApnFallbackManager.class);
private final FeatureFlagsManager featureFlagsManager = mock(FeatureFlagsManager.class);
private final ObjectMapper mapper = new ObjectMapper();
@@ -281,7 +279,7 @@ public class MessageControllerTest {
OutgoingMessageEntityList messagesList = new OutgoingMessageEntityList(messages, false);
when(messagesManager.getMessagesForDevice(eq(AuthHelper.VALID_NUMBER), eq(AuthHelper.VALID_UUID), eq(1L), anyString(), anyBoolean())).thenReturn(messagesList);
when(messagesManager.getMessagesForDevice(eq(AuthHelper.VALID_UUID), eq(1L), anyString(), anyBoolean())).thenReturn(messagesList);
OutgoingMessageEntityList response =
resources.getJerseyTest().target("/v1/messages/")
@@ -318,7 +316,7 @@ public class MessageControllerTest {
OutgoingMessageEntityList messagesList = new OutgoingMessageEntityList(messages, false);
when(messagesManager.getMessagesForDevice(eq(AuthHelper.VALID_NUMBER), eq(AuthHelper.VALID_UUID), eq(1L), anyString(), anyBoolean())).thenReturn(messagesList);
when(messagesManager.getMessagesForDevice(eq(AuthHelper.VALID_UUID), eq(1L), anyString(), anyBoolean())).thenReturn(messagesList);
Response response =
resources.getJerseyTest().target("/v1/messages/")
@@ -336,20 +334,20 @@ public class MessageControllerTest {
UUID sourceUuid = UUID.randomUUID();
when(messagesManager.delete(AuthHelper.VALID_NUMBER, AuthHelper.VALID_UUID, 1, "+14152222222", 31337))
when(messagesManager.delete(AuthHelper.VALID_UUID, 1, "+14152222222", 31337))
.thenReturn(Optional.of(new OutgoingMessageEntity(31337L, true, null,
Envelope.Type.CIPHERTEXT_VALUE,
null, timestamp,
"+14152222222", sourceUuid, 1, "hi".getBytes(), null, 0)));
when(messagesManager.delete(AuthHelper.VALID_NUMBER, AuthHelper.VALID_UUID, 1, "+14152222222", 31338))
when(messagesManager.delete(AuthHelper.VALID_UUID, 1, "+14152222222", 31338))
.thenReturn(Optional.of(new OutgoingMessageEntity(31337L, true, null,
Envelope.Type.RECEIPT_VALUE,
null, System.currentTimeMillis(),
"+14152222222", sourceUuid, 1, null, null, 0)));
when(messagesManager.delete(AuthHelper.VALID_NUMBER, AuthHelper.VALID_UUID, 1, "+14152222222", 31339))
when(messagesManager.delete(AuthHelper.VALID_UUID, 1, "+14152222222", 31339))
.thenReturn(Optional.empty());
Response response = resources.getJerseyTest()

View File

@@ -1,317 +0,0 @@
/*
* Copyright 2013-2020 Signal Messenger, LLC
* SPDX-License-Identifier: AGPL-3.0-only
*/
package org.whispersystems.textsecuregcm.tests.storage;
import com.google.protobuf.ByteString;
import com.opentable.db.postgres.embedded.LiquibasePreparer;
import com.opentable.db.postgres.junit.EmbeddedPostgresRules;
import com.opentable.db.postgres.junit.PreparedDbRule;
import junitparams.JUnitParamsRunner;
import junitparams.Parameters;
import org.jdbi.v3.core.Jdbi;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.whispersystems.textsecuregcm.configuration.CircuitBreakerConfiguration;
import org.whispersystems.textsecuregcm.entities.MessageProtos.Envelope;
import org.whispersystems.textsecuregcm.entities.OutgoingMessageEntity;
import org.whispersystems.textsecuregcm.storage.FaultTolerantDatabase;
import org.whispersystems.textsecuregcm.storage.Messages;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.Optional;
import java.util.Queue;
import java.util.Random;
import java.util.UUID;
import java.util.concurrent.ThreadLocalRandom;
import java.util.stream.Collectors;
import static org.assertj.core.api.AssertionsForClassTypes.assertThat;
@RunWith(JUnitParamsRunner.class)
public class MessagesTest {
@Rule
public PreparedDbRule db = EmbeddedPostgresRules.preparedDatabase(LiquibasePreparer.forClasspathLocation("messagedb.xml"));
private Messages messages;
private long serialTimestamp = 0;
@Before
public void setupAccountsDao() {
this.messages = new Messages(new FaultTolerantDatabase("messages-test", Jdbi.create(db.getTestDatabase()), new CircuitBreakerConfiguration()));
}
@Test
public void testStore() throws SQLException {
Envelope envelope = generateEnvelope();
messages.store(List.of(envelope), "+14151112222", 1);
PreparedStatement statement = db.getTestDatabase().getConnection().prepareStatement("SELECT * FROM messages WHERE destination = ?");
statement.setString(1, "+14151112222");
ResultSet resultSet = statement.executeQuery();
assertThat(resultSet.next()).isTrue();
assertThat(resultSet.getString("guid")).isEqualTo(envelope.getServerGuid());
assertThat(resultSet.getInt("type")).isEqualTo(envelope.getType().getNumber());
assertThat(resultSet.getString("relay")).isNullOrEmpty();
assertThat(resultSet.getLong("timestamp")).isEqualTo(envelope.getTimestamp());
assertThat(resultSet.getLong("server_timestamp")).isEqualTo(envelope.getServerTimestamp());
assertThat(resultSet.getString("source")).isEqualTo(envelope.getSource());
assertThat(resultSet.getLong("source_device")).isEqualTo(envelope.getSourceDevice());
assertThat(resultSet.getBytes("message")).isEqualTo(envelope.getLegacyMessage().toByteArray());
assertThat(resultSet.getBytes("content")).isEqualTo(envelope.getContent().toByteArray());
assertThat(resultSet.getString("destination")).isEqualTo("+14151112222");
assertThat(resultSet.getLong("destination_device")).isEqualTo(1);
assertThat(resultSet.next()).isFalse();
}
@Test
@Parameters(method = "argumentsForTestStoreSealedSenderBatch")
public void testStoreSealedSenderBatch(final List<Boolean> sealedSenderSequence) throws Exception {
final String destinationNumber = "+14151234567";
final List<Envelope> envelopes = sealedSenderSequence.stream()
.map(sealedSender -> {
if (sealedSender) {
return generateEnvelope().toBuilder().clearSourceUuid().clearSource().clearSourceDevice().build();
} else {
return generateEnvelope().toBuilder().setSourceUuid(UUID.randomUUID().toString()).setSource("+18005551234").setSourceDevice(4).build();
}
}).collect(Collectors.toList());
messages.store(envelopes, destinationNumber, 1);
final Queue<Envelope> expectedMessages = new ArrayDeque<>(envelopes);
try (final PreparedStatement statement = db.getTestDatabase().getConnection().prepareStatement("SELECT * FROM messages WHERE destination = ?")) {
statement.setString(1, destinationNumber);
try (final ResultSet resultSet = statement.executeQuery()) {
while (resultSet.next() && !expectedMessages.isEmpty()) {
assertRowEqualsEnvelope(resultSet, destinationNumber, expectedMessages.poll());
}
assertThat(resultSet.next()).isFalse();
assertThat(expectedMessages.isEmpty());
}
}
}
private static Object argumentsForTestStoreSealedSenderBatch() {
return new Object[] {
List.of(true),
List.of(false),
List.of(true, false),
List.of(false, true)
};
}
private void assertRowEqualsEnvelope(final ResultSet resultSet, final String expectedDestination, final Envelope expectedMessage) throws SQLException {
assertThat(resultSet.getString("guid")).isEqualTo(expectedMessage.getServerGuid());
assertThat(resultSet.getInt("type")).isEqualTo(expectedMessage.getType().getNumber());
assertThat(resultSet.getString("relay")).isNullOrEmpty();
assertThat(resultSet.getLong("timestamp")).isEqualTo(expectedMessage.getTimestamp());
assertThat(resultSet.getLong("server_timestamp")).isEqualTo(expectedMessage.getServerTimestamp());
assertThat(resultSet.getBytes("message")).isEqualTo(expectedMessage.getLegacyMessage().toByteArray());
assertThat(resultSet.getBytes("content")).isEqualTo(expectedMessage.getContent().toByteArray());
assertThat(resultSet.getString("destination")).isEqualTo(expectedDestination);
assertThat(resultSet.getLong("destination_device")).isEqualTo(1);
if (expectedMessage.hasSource()) {
assertThat(resultSet.getString("source")).isEqualTo(expectedMessage.getSource());
} else {
assertThat(resultSet.getString("source")).isNullOrEmpty();
}
if (expectedMessage.hasSourceDevice()) {
assertThat(resultSet.getLong("source_device")).isEqualTo(expectedMessage.getSourceDevice());
} else {
assertThat(resultSet.getLong("source_device")).isEqualTo(0);
}
if (expectedMessage.hasSourceUuid()) {
assertThat(resultSet.getString("source_uuid")).isEqualTo(expectedMessage.getSourceUuid());
} else {
assertThat(resultSet.getString("source_uuid")).isNull();
}
}
@Test
public void testLoad() {
List<Envelope> inserted = insertRandom("+14151112222", 1);
inserted.sort(Comparator.comparingLong(Envelope::getTimestamp));
List<OutgoingMessageEntity> retrieved = messages.load("+14151112222", 1);
assertThat(retrieved.size()).isEqualTo(inserted.size());
for (int i=0;i<retrieved.size();i++) {
verifyExpected(retrieved.get(i), inserted.get(i), UUID.fromString(inserted.get(i).getServerGuid()));
}
}
@Test
public void removeBySourceDestinationTimestamp() {
List<Envelope> inserted = insertRandom("+14151112222", 1);
List<Envelope> unrelated = insertRandom("+14151114444", 3);
Envelope toRemove = inserted.remove(new Random(System.currentTimeMillis()).nextInt(inserted.size() - 1));
Optional<OutgoingMessageEntity> removed = messages.remove("+14151112222", 1, toRemove.getSource(), toRemove.getTimestamp());
assertThat(removed.isPresent()).isTrue();
verifyExpected(removed.get(), toRemove, UUID.fromString(toRemove.getServerGuid()));
verifyInTact(inserted, "+14151112222", 1);
verifyInTact(unrelated, "+14151114444", 3);
}
@Test
public void removeByDestinationGuid() {
List<Envelope> unrelated = insertRandom("+14151113333", 2);
List<Envelope> inserted = insertRandom("+14151112222", 1);
Envelope toRemove = inserted.remove(new Random(System.currentTimeMillis()).nextInt(inserted.size() - 1));
Optional<OutgoingMessageEntity> removed = messages.remove("+14151112222", UUID.fromString(toRemove.getServerGuid()));
assertThat(removed.isPresent()).isTrue();
verifyExpected(removed.get(), toRemove, UUID.fromString(toRemove.getServerGuid()));
verifyInTact(inserted, "+14151112222", 1);
verifyInTact(unrelated, "+14151113333", 2);
}
@Test
public void removeByDestinationRowId() {
List<Envelope> unrelatedInserted = insertRandom("+14151111111", 1);
List<Envelope> inserted = insertRandom("+14151112222", 1);
inserted.sort(Comparator.comparingLong(Envelope::getTimestamp));
List<OutgoingMessageEntity> retrieved = messages.load("+14151112222", 1);
int toRemoveIndex = new Random(System.currentTimeMillis()).nextInt(inserted.size() - 1);
inserted.remove(toRemoveIndex);
messages.remove("+14151112222", retrieved.get(toRemoveIndex).getId());
verifyInTact(inserted, "+14151112222", 1);
verifyInTact(unrelatedInserted, "+14151111111", 1);
}
@Test
public void testLoadEmpty() {
insertRandom("+14151112222", 1);
assertThat(messages.load("+14159999999", 1).isEmpty()).isTrue();
}
@Test
public void testClearDestination() {
insertRandom("+14151112222", 1);
insertRandom("+14151112222", 2);
List<Envelope> unrelated = insertRandom("+14151111111", 1);
messages.clear("+14151112222");
assertThat(messages.load("+14151112222", 1).isEmpty()).isTrue();
verifyInTact(unrelated, "+14151111111", 1);
}
@Test
public void testClearDestinationDevice() {
insertRandom("+14151112222", 1);
List<Envelope> inserted = insertRandom("+14151112222", 2);
List<Envelope> unrelated = insertRandom("+14151111111", 1);
messages.clear("+14151112222", 1);
assertThat(messages.load("+14151112222", 1).isEmpty()).isTrue();
verifyInTact(inserted, "+14151112222", 2);
verifyInTact(unrelated, "+14151111111", 1);
}
@Test
public void testVacuum() {
List<Envelope> inserted = insertRandom("+14151112222", 2);
messages.vacuum();
verifyInTact(inserted, "+14151112222", 2);
}
private List<Envelope> insertRandom(String destination, int destinationDevice) {
List<Envelope> inserted = new ArrayList<>(50);
for (int i=0;i<50;i++) {
inserted.add(generateEnvelope());
}
messages.store(inserted, destination, destinationDevice);
return inserted;
}
private void verifyInTact(List<Envelope> inserted, String destination, int destinationDevice) {
inserted.sort(Comparator.comparingLong(Envelope::getTimestamp));
List<OutgoingMessageEntity> retrieved = messages.load(destination, destinationDevice);
assertThat(retrieved.size()).isEqualTo(inserted.size());
for (int i=0;i<retrieved.size();i++) {
verifyExpected(retrieved.get(i), inserted.get(i), UUID.fromString(inserted.get(i).getServerGuid()));
}
}
private void verifyExpected(OutgoingMessageEntity retrieved, Envelope inserted, UUID guid) {
assertThat(retrieved.getTimestamp()).isEqualTo(inserted.getTimestamp());
assertThat(retrieved.getSource()).isEqualTo(inserted.getSource());
assertThat(retrieved.getRelay()).isEqualTo(inserted.getRelay());
assertThat(retrieved.getType()).isEqualTo(inserted.getType().getNumber());
assertThat(retrieved.getContent()).isEqualTo(inserted.getContent().toByteArray());
assertThat(retrieved.getMessage()).isEqualTo(inserted.getLegacyMessage().toByteArray());
assertThat(retrieved.getServerTimestamp()).isEqualTo(inserted.getServerTimestamp());
assertThat(retrieved.getGuid()).isEqualTo(guid);
assertThat(retrieved.getSourceDevice()).isEqualTo(inserted.getSourceDevice());
}
private Envelope generateEnvelope() {
Random random = new Random();
byte[] content = new byte[256];
byte[] legacy = new byte[200];
Arrays.fill(content, (byte)random.nextInt(255));
Arrays.fill(legacy, (byte)random.nextInt(255));
return Envelope.newBuilder()
.setServerGuid(UUID.randomUUID().toString())
.setSourceDevice(random.nextInt(10000))
.setSource("testSource" + random.nextInt())
.setTimestamp(serialTimestamp++)
.setServerTimestamp(serialTimestamp++)
.setLegacyMessage(ByteString.copyFrom(legacy))
.setContent(ByteString.copyFrom(content))
.setType(Envelope.Type.CIPHERTEXT)
.setServerGuid(UUID.randomUUID().toString())
.build();
}
}