JAMES-2554 Add test on Cassandra MailRepository storing implementation The aim of those tests is to prouve the order of storing data: MimeMessage -> message blob parts -> keys -> mail repository size
Project: http://git-wip-us.apache.org/repos/asf/james-project/repo Commit: http://git-wip-us.apache.org/repos/asf/james-project/commit/e536e62f Tree: http://git-wip-us.apache.org/repos/asf/james-project/tree/e536e62f Diff: http://git-wip-us.apache.org/repos/asf/james-project/diff/e536e62f Branch: refs/heads/master Commit: e536e62fabe75a5463f345a4b72db5f8dcadc162 Parents: 33bfd0d Author: Antoine Duprat <adup...@linagora.com> Authored: Mon Oct 8 15:20:36 2018 +0200 Committer: Benoit Tellier <btell...@linagora.com> Committed: Wed Oct 10 15:47:38 2018 +0700 ---------------------------------------------------------------------- ...ilRepositoryWithFakeImplementationsTest.java | 291 +++++++++++++++++++ 1 file changed, 291 insertions(+) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/james-project/blob/e536e62f/server/mailrepository/mailrepository-cassandra/src/test/java/org/apache/james/mailrepository/cassandra/CassandraMailRepositoryWithFakeImplementationsTest.java ---------------------------------------------------------------------- diff --git a/server/mailrepository/mailrepository-cassandra/src/test/java/org/apache/james/mailrepository/cassandra/CassandraMailRepositoryWithFakeImplementationsTest.java b/server/mailrepository/mailrepository-cassandra/src/test/java/org/apache/james/mailrepository/cassandra/CassandraMailRepositoryWithFakeImplementationsTest.java new file mode 100644 index 0000000..75aa16a --- /dev/null +++ b/server/mailrepository/mailrepository-cassandra/src/test/java/org/apache/james/mailrepository/cassandra/CassandraMailRepositoryWithFakeImplementationsTest.java @@ -0,0 +1,291 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.james.mailrepository.cassandra; + +import com.datastax.driver.core.ResultSet; +import com.datastax.driver.core.Session; +import com.google.common.collect.ImmutableList; +import org.apache.james.backends.cassandra.CassandraCluster; +import org.apache.james.backends.cassandra.CassandraClusterExtension; +import org.apache.james.backends.cassandra.components.CassandraModule; +import org.apache.james.backends.cassandra.init.CassandraTypesProvider; +import org.apache.james.backends.cassandra.utils.CassandraUtils; +import org.apache.james.blob.api.BlobId; +import org.apache.james.blob.api.HashBlobId; +import org.apache.james.blob.api.Store; +import org.apache.james.blob.cassandra.BlobTable; +import org.apache.james.blob.cassandra.CassandraBlobModule; +import org.apache.james.blob.cassandra.CassandraBlobsDAO; +import org.apache.james.blob.mail.MimeMessagePartsId; +import org.apache.james.blob.mail.MimeMessageStore; +import org.apache.james.core.MailAddress; +import org.apache.james.core.builder.MimeMessageBuilder; +import org.apache.james.mailrepository.api.MailKey; +import org.apache.james.mailrepository.api.MailRepositoryUrl; +import org.apache.james.server.core.MailImpl; +import org.apache.mailet.Mail; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.junit.jupiter.api.extension.ExtensionContext; + +import javax.mail.MessagingException; +import javax.mail.internet.MimeMessage; +import java.util.List; +import java.util.concurrent.CompletableFuture; + +import static com.datastax.driver.core.querybuilder.QueryBuilder.select; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +@ExtendWith(CassandraMailRepositoryWithFakeImplementationsTest.MailRepositoryCassandraClusterExtension.class) +class CassandraMailRepositoryWithFakeImplementationsTest { + static final MailRepositoryUrl URL = MailRepositoryUrl.from("proto://url"); + static final HashBlobId.Factory BLOB_ID_FACTORY = new HashBlobId.Factory(); + + static class MailRepositoryCassandraClusterExtension extends CassandraClusterExtension { + public MailRepositoryCassandraClusterExtension() { + super(CassandraModule.aggregateModules( + CassandraMailRepositoryModule.MODULE, + CassandraBlobModule.MODULE)); + } + + @Override + public void afterAll(ExtensionContext extensionContext) { + } + } + + @Nested + class FailingStoreTest { + CassandraMailRepository cassandraMailRepository; + CassandraMailRepositoryKeysDAO keysDAO; + + @BeforeEach + void setup(CassandraCluster cassandra) { + CassandraMailRepositoryMailDAO mailDAO = new CassandraMailRepositoryMailDAO(cassandra.getConf(), BLOB_ID_FACTORY, cassandra.getTypesProvider()); + keysDAO = new CassandraMailRepositoryKeysDAO(cassandra.getConf(), CassandraUtils.WITH_DEFAULT_CONFIGURATION); + CassandraMailRepositoryCountDAO countDAO = new CassandraMailRepositoryCountDAO(cassandra.getConf()); + CassandraBlobsDAO blobsDAO = new CassandraBlobsDAO(cassandra.getConf()); + + cassandraMailRepository = new CassandraMailRepository(URL, + keysDAO, countDAO, mailDAO, new FailingStore()); + } + + class FailingStore implements Store<MimeMessage, MimeMessagePartsId> { + + @Override + public CompletableFuture<MimeMessagePartsId> save(MimeMessage mimeMessage) { + return CompletableFuture.supplyAsync(() -> { + throw new RuntimeException("Expected failure while saving"); + }); + } + + @Override + public CompletableFuture<MimeMessage> read(MimeMessagePartsId blobIds) { + return CompletableFuture.supplyAsync(() -> { + throw new RuntimeException("Expected failure while reading"); + }); + } + } + + @Test + void keysShouldNotBeStoredWhenStoringMimeMessageHasFailed() throws Exception { + MailKey mailKey = new MailKey("mymail"); + List<MailAddress> recipients = ImmutableList + .of(new MailAddress("r...@domain.com"), + new MailAddress("r...@domain.com")); + MimeMessage mailContent = MimeMessageBuilder.mimeMessageBuilder() + .setSubject("test") + .setText("this is the content") + .build(); + MailImpl mail = new MailImpl(mailKey.asString(), new MailAddress("sen...@domain.com"), recipients, mailContent); + + assertThatThrownBy(() -> cassandraMailRepository.store(mail)) + .isInstanceOf(RuntimeException.class) + .hasMessage("java.lang.RuntimeException: Expected failure while saving"); + + assertThat(keysDAO.list(URL).join()).isEmpty(); + } + } + + @Nested + class FailingMailDaoTest { + CassandraMailRepository cassandraMailRepository; + CassandraMailRepositoryKeysDAO keysDAO; + + @BeforeEach + void setup(CassandraCluster cassandra) { + FailingMailDAO mailDAO = new FailingMailDAO(cassandra.getConf(), BLOB_ID_FACTORY, cassandra.getTypesProvider()); + keysDAO = new CassandraMailRepositoryKeysDAO(cassandra.getConf(), CassandraUtils.WITH_DEFAULT_CONFIGURATION); + CassandraMailRepositoryCountDAO countDAO = new CassandraMailRepositoryCountDAO(cassandra.getConf()); + CassandraBlobsDAO blobsDAO = new CassandraBlobsDAO(cassandra.getConf()); + + cassandraMailRepository = new CassandraMailRepository(URL, + keysDAO, countDAO, mailDAO, MimeMessageStore.factory(blobsDAO).mimeMessageStore()); + } + + class FailingMailDAO extends CassandraMailRepositoryMailDAO { + + public FailingMailDAO(Session session, BlobId.Factory blobIdFactory, CassandraTypesProvider cassandraTypesProvider) { + super(session, blobIdFactory, cassandraTypesProvider); + } + + @Override + public CompletableFuture<Void> store(MailRepositoryUrl url, Mail mail, BlobId headerId, BlobId bodyId) throws MessagingException { + return CompletableFuture.supplyAsync(() -> { + throw new RuntimeException("Expected failure while storing mail parts"); + }); + } + } + + @Test + void keysShouldNotBeStoredWhenStoringMailPartsHasFailed() throws Exception { + MailKey mailKey = new MailKey("mymail"); + List<MailAddress> recipients = ImmutableList + .of(new MailAddress("r...@domain.com"), + new MailAddress("r...@domain.com")); + MimeMessage mailContent = MimeMessageBuilder.mimeMessageBuilder() + .setSubject("test") + .setText("this is the content") + .build(); + MailImpl mail = new MailImpl(mailKey.asString(), new MailAddress("sen...@domain.com"), recipients, mailContent); + + assertThatThrownBy(() -> cassandraMailRepository.store(mail)) + .isInstanceOf(RuntimeException.class) + .hasMessage("java.lang.RuntimeException: Expected failure while storing mail parts"); + + assertThat(keysDAO.list(URL).join()).isEmpty(); + } + + @Test + void mimeMessageShouldBeStoredWhenStoringMailPartsHasFailed(CassandraCluster cassandra) throws Exception { + MailKey mailKey = new MailKey("mymail"); + List<MailAddress> recipients = ImmutableList + .of(new MailAddress("r...@domain.com"), + new MailAddress("r...@domain.com")); + MimeMessage mailContent = MimeMessageBuilder.mimeMessageBuilder() + .setSubject("test") + .setText("this is the content") + .build(); + MailImpl mail = new MailImpl(mailKey.asString(), new MailAddress("sen...@domain.com"), recipients, mailContent); + + assertThatThrownBy(() -> cassandraMailRepository.store(mail)) + .isInstanceOf(RuntimeException.class) + .hasMessage("java.lang.RuntimeException: Expected failure while storing mail parts"); + + ResultSet resultSet = cassandra.getConf().execute(select() + .from(BlobTable.TABLE_NAME)); + assertThat(resultSet.all()).hasSize(2); + } + } + + @Nested + class FailingKeysDaoTest { + CassandraMailRepository cassandraMailRepository; + CassandraMailRepositoryCountDAO countDAO; + + @BeforeEach + void setup(CassandraCluster cassandra) { + CassandraMailRepositoryMailDAO mailDAO = new CassandraMailRepositoryMailDAO(cassandra.getConf(), BLOB_ID_FACTORY, cassandra.getTypesProvider()); + FailingKeysDAO keysDAO = new FailingKeysDAO(cassandra.getConf(), CassandraUtils.WITH_DEFAULT_CONFIGURATION); + countDAO = new CassandraMailRepositoryCountDAO(cassandra.getConf()); + CassandraBlobsDAO blobsDAO = new CassandraBlobsDAO(cassandra.getConf()); + + cassandraMailRepository = new CassandraMailRepository(URL, + keysDAO, countDAO, mailDAO, MimeMessageStore.factory(blobsDAO).mimeMessageStore()); + } + + class FailingKeysDAO extends CassandraMailRepositoryKeysDAO { + + public FailingKeysDAO(Session session, CassandraUtils cassandraUtils) { + super(session, cassandraUtils); + } + + @Override + public CompletableFuture<Boolean> store(MailRepositoryUrl url, MailKey key) { + return CompletableFuture.supplyAsync(() -> { + throw new RuntimeException("Expected failure while storing keys"); + }); + } + } + + @Test + void sizeShouldNotBeIncreasedWhenStoringKeysHasFailed() throws Exception { + MailKey mailKey = new MailKey("mymail"); + List<MailAddress> recipients = ImmutableList + .of(new MailAddress("r...@domain.com"), + new MailAddress("r...@domain.com")); + MimeMessage mailContent = MimeMessageBuilder.mimeMessageBuilder() + .setSubject("test") + .setText("this is the content") + .build(); + MailImpl mail = new MailImpl(mailKey.asString(), new MailAddress("sen...@domain.com"), recipients, mailContent); + + assertThatThrownBy(() -> cassandraMailRepository.store(mail)) + .isInstanceOf(RuntimeException.class) + .hasMessage("java.lang.RuntimeException: Expected failure while storing keys"); + + assertThat(countDAO.getCount(URL).join()).isEqualTo(0); + } + + @Test + void mimeMessageShouldBeStoredWhenStoringKeysHasFailed(CassandraCluster cassandra) throws Exception { + MailKey mailKey = new MailKey("mymail"); + List<MailAddress> recipients = ImmutableList + .of(new MailAddress("r...@domain.com"), + new MailAddress("r...@domain.com")); + MimeMessage mailContent = MimeMessageBuilder.mimeMessageBuilder() + .setSubject("test") + .setText("this is the content") + .build(); + MailImpl mail = new MailImpl(mailKey.asString(), new MailAddress("sen...@domain.com"), recipients, mailContent); + + assertThatThrownBy(() -> cassandraMailRepository.store(mail)) + .isInstanceOf(RuntimeException.class) + .hasMessage("java.lang.RuntimeException: Expected failure while storing keys"); + + ResultSet resultSet = cassandra.getConf().execute(select() + .from(BlobTable.TABLE_NAME)); + assertThat(resultSet.all()).hasSize(2); + } + + @Test + void mailPartsShouldBeStoredWhenStoringKeysHasFailed(CassandraCluster cassandra) throws Exception { + MailKey mailKey = new MailKey("mymail"); + List<MailAddress> recipients = ImmutableList + .of(new MailAddress("r...@domain.com"), + new MailAddress("r...@domain.com")); + MimeMessage mailContent = MimeMessageBuilder.mimeMessageBuilder() + .setSubject("test") + .setText("this is the content") + .build(); + MailImpl mail = new MailImpl(mailKey.asString(), new MailAddress("sen...@domain.com"), recipients, mailContent); + + assertThatThrownBy(() -> cassandraMailRepository.store(mail)) + .isInstanceOf(RuntimeException.class) + .hasMessage("java.lang.RuntimeException: Expected failure while storing keys"); + + ResultSet resultSet = cassandra.getConf().execute(select() + .from(MailRepositoryTable.CONTENT_TABLE_NAME)); + assertThat(resultSet.all()).hasSize(1); + } + } +} \ No newline at end of file --------------------------------------------------------------------- To unsubscribe, e-mail: server-dev-unsubscr...@james.apache.org For additional commands, e-mail: server-dev-h...@james.apache.org