This is an automated email from the ASF dual-hosted git repository. btellier pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/james-project.git
commit e7675be78f43dfaaba9e250ff8306f7422b3a61e Author: Benoit Tellier <btell...@linagora.com> AuthorDate: Tue Mar 5 11:39:06 2019 +0700 JAMES-2665 Basic first integration test for memory and the vault Exercise it on the various type of mail repositories --- .../mailbox/PreDeletionHookConfiguration.java | 5 + .../mailbox/PreDeletionHooksConfiguration.java | 4 + .../integration/DeletedMessagesVaultTest.java | 191 +++++++++++++++++++++ .../memory/MemoryDeletedMessagesVaultTest.java | 50 ++++++ ...moryFileRepositoryDeletedMessagesVaultTest.java | 50 ++++++ .../src/test/resources/mailrepositorystore.xml | 7 + 6 files changed, 307 insertions(+) diff --git a/server/container/guice/mailbox/src/main/java/org/apache/james/modules/mailbox/PreDeletionHookConfiguration.java b/server/container/guice/mailbox/src/main/java/org/apache/james/modules/mailbox/PreDeletionHookConfiguration.java index 9e36255..e0a22f1 100644 --- a/server/container/guice/mailbox/src/main/java/org/apache/james/modules/mailbox/PreDeletionHookConfiguration.java +++ b/server/container/guice/mailbox/src/main/java/org/apache/james/modules/mailbox/PreDeletionHookConfiguration.java @@ -22,6 +22,7 @@ import java.util.Objects; import org.apache.commons.configuration.ConfigurationException; import org.apache.commons.configuration.HierarchicalConfiguration; +import org.apache.james.mailbox.extension.PreDeletionHook; import com.google.common.base.Preconditions; import com.google.common.base.Strings; @@ -40,6 +41,10 @@ public class PreDeletionHookConfiguration { } } + public static PreDeletionHookConfiguration forClass(Class<? extends PreDeletionHook> clazz) { + return forClass(clazz.getName()); + } + public static PreDeletionHookConfiguration forClass(String clazz) { return new PreDeletionHookConfiguration(clazz); } diff --git a/server/container/guice/mailbox/src/main/java/org/apache/james/modules/mailbox/PreDeletionHooksConfiguration.java b/server/container/guice/mailbox/src/main/java/org/apache/james/modules/mailbox/PreDeletionHooksConfiguration.java index 14df7cb..eab2fcc 100644 --- a/server/container/guice/mailbox/src/main/java/org/apache/james/modules/mailbox/PreDeletionHooksConfiguration.java +++ b/server/container/guice/mailbox/src/main/java/org/apache/james/modules/mailbox/PreDeletionHooksConfiguration.java @@ -40,6 +40,10 @@ public class PreDeletionHooksConfiguration { .collect(Guavate.toImmutableList())); } + public static PreDeletionHooksConfiguration forHooks(PreDeletionHookConfiguration... hooks) { + return new PreDeletionHooksConfiguration(ImmutableList.copyOf(hooks)); + } + public static PreDeletionHooksConfiguration none() { return new PreDeletionHooksConfiguration(ImmutableList.of()); } diff --git a/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/java/org/apache/james/jmap/methods/integration/DeletedMessagesVaultTest.java b/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/java/org/apache/james/jmap/methods/integration/DeletedMessagesVaultTest.java new file mode 100644 index 0000000..ba529c7 --- /dev/null +++ b/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/java/org/apache/james/jmap/methods/integration/DeletedMessagesVaultTest.java @@ -0,0 +1,191 @@ +/**************************************************************** + * 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.jmap.methods.integration; + +import static io.restassured.RestAssured.given; +import static io.restassured.RestAssured.with; +import static org.apache.james.jmap.HttpJmapAuthentication.authenticateJamesUser; +import static org.apache.james.jmap.JmapCommonRequests.getOutboxId; +import static org.apache.james.jmap.JmapCommonRequests.listMessageIdsForAccount; +import static org.apache.james.jmap.JmapURIBuilder.baseUri; +import static org.apache.james.jmap.TestingConstants.ARGUMENTS; +import static org.apache.james.jmap.TestingConstants.DOMAIN; +import static org.apache.james.jmap.TestingConstants.calmlyAwait; +import static org.apache.james.jmap.TestingConstants.jmapRequestSpecBuilder; +import static org.hamcrest.Matchers.hasItem; +import static org.hamcrest.Matchers.is; + +import java.io.IOException; +import java.util.List; +import java.util.stream.Collectors; + +import org.apache.james.GuiceJamesServer; +import org.apache.james.jmap.api.access.AccessToken; +import org.apache.james.jmap.categories.BasicFeature; +import org.apache.james.mailbox.DefaultMailboxes; +import org.apache.james.mailbox.probe.MailboxProbe; +import org.apache.james.modules.MailboxProbeImpl; +import org.apache.james.probe.DataProbe; +import org.apache.james.utils.DataProbeImpl; +import org.apache.james.utils.JmapGuiceProbe; +import org.apache.james.utils.WebAdminGuiceProbe; +import org.apache.james.webadmin.WebAdminUtils; +import org.apache.james.webadmin.routes.TasksRoutes; +import org.awaitility.Duration; +import org.awaitility.core.ConditionFactory; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.junit.experimental.categories.Category; + +import com.google.common.base.Strings; + +import io.restassured.RestAssured; +import io.restassured.parsing.Parser; +import io.restassured.specification.RequestSpecification; + +public abstract class DeletedMessagesVaultTest { + private static final String HOMER = "homer@" + DOMAIN; + private static final String BART = "bart@" + DOMAIN; + private static final String PASSWORD = "password"; + private static final String BOB_PASSWORD = "bobPassword"; + private static final ConditionFactory WAIT_TWO_MINUTES = calmlyAwait.atMost(Duration.TWO_MINUTES); + private static final String SUBJECT = "This mail will be restored from the vault!!"; + + protected abstract GuiceJamesServer createJmapServer() throws IOException; + + private AccessToken homerAccessToken; + private AccessToken bartAccessToken; + private GuiceJamesServer jmapServer; + private RequestSpecification webAdminApi; + + @Before + public void setup() throws Throwable { + jmapServer = createJmapServer(); + jmapServer.start(); + MailboxProbe mailboxProbe = jmapServer.getProbe(MailboxProbeImpl.class); + DataProbe dataProbe = jmapServer.getProbe(DataProbeImpl.class); + + RestAssured.requestSpecification = jmapRequestSpecBuilder + .setPort(jmapServer.getProbe(JmapGuiceProbe.class).getJmapPort()) + .build(); + RestAssured.defaultParser = Parser.JSON; + + dataProbe.addDomain(DOMAIN); + dataProbe.addUser(HOMER, PASSWORD); + dataProbe.addUser(BART, BOB_PASSWORD); + mailboxProbe.createMailbox("#private", HOMER, DefaultMailboxes.INBOX); + homerAccessToken = authenticateJamesUser(baseUri(jmapServer), HOMER, PASSWORD); + bartAccessToken = authenticateJamesUser(baseUri(jmapServer), BART, BOB_PASSWORD); + + WebAdminGuiceProbe webAdminGuiceProbe = jmapServer.getProbe(WebAdminGuiceProbe.class); + webAdminGuiceProbe.await(); + webAdminApi = given() + .spec(WebAdminUtils + .buildRequestSpecification(webAdminGuiceProbe.getWebAdminPort()) + .build()); + } + + @After + public void tearDown() { + jmapServer.stop(); + } + + @Category(BasicFeature.class) + @Test + public void shouldSendANoticeWhenThresholdExceeded() { + bartSendMessageToHomer(); + WAIT_TWO_MINUTES.until(() -> listMessageIdsForAccount(homerAccessToken).size() == 1); + + homerDeletesMessages(listMessageIdsForAccount(homerAccessToken)); + WAIT_TWO_MINUTES.until(() -> listMessageIdsForAccount(homerAccessToken).size() == 0); + + restoreAllMessagesOfHomer(); + WAIT_TWO_MINUTES.until(() -> listMessageIdsForAccount(homerAccessToken).size() == 1); + + String messageId = listMessageIdsForAccount(homerAccessToken).get(0); + given() + .header("Authorization", homerAccessToken.serialize()) + .body("[[\"getMessages\", {\"ids\": [\"" + messageId + "\"]}, \"#0\"]]") + .when() + .post("/jmap") + .then() + .statusCode(200) + .log().ifValidationFails() + .body(ARGUMENTS + ".list.subject", hasItem(SUBJECT)); + } + + private void bartSendMessageToHomer() { + String messageCreationId = "creationId"; + String outboxId = getOutboxId(bartAccessToken); + String bigEnoughBody = Strings.repeat("123456789\n", 12 * 100); + String requestBody = "[" + + " [" + + " \"setMessages\"," + + " {" + + " \"create\": { \"" + messageCreationId + "\" : {" + + " \"headers\":{\"Disposition-Notification-To\":\"" + BART + "\"}," + + " \"from\": { \"name\": \"Bob\", \"email\": \"" + BART + "\"}," + + " \"to\": [{ \"name\": \"User\", \"email\": \"" + HOMER + "\"}]," + + " \"subject\": \"" + SUBJECT + "\"," + + " \"textBody\": \"" + bigEnoughBody + "\"," + + " \"htmlBody\": \"Test <b>body</b>, HTML version\"," + + " \"mailboxIds\": [\"" + outboxId + "\"] " + + " }}" + + " }," + + " \"#0\"" + + " ]" + + "]"; + + with() + .header("Authorization", bartAccessToken.serialize()) + .body(requestBody) + .post("/jmap") + .then() + .extract() + .body() + .path(ARGUMENTS + ".created." + messageCreationId + ".id"); + } + + private void homerDeletesMessages(List<String> idsToDestroy) { + String idString = idsToDestroy.stream() + .map(id -> "\"" + id + "\"") + .collect(Collectors.joining(",")); + + with() + .header("Authorization", homerAccessToken.serialize()) + .body("[[\"setMessages\", {\"destroy\": [" + idString + "]}, \"#0\"]]") + .post("/jmap"); + } + + private void restoreAllMessagesOfHomer() { + String taskId = webAdminApi.with() + .post("/deletedMessages/user/" + HOMER + "?action=restore") + .jsonPath() + .get("taskId"); + + webAdminApi.given() + .basePath(TasksRoutes.BASE) + .when() + .get(taskId + "/await") + .then() + .body("status", is("completed")); + } +} diff --git a/server/protocols/jmap-integration-testing/memory-jmap-integration-testing/src/test/java/org/apache/james/jmap/memory/MemoryDeletedMessagesVaultTest.java b/server/protocols/jmap-integration-testing/memory-jmap-integration-testing/src/test/java/org/apache/james/jmap/memory/MemoryDeletedMessagesVaultTest.java new file mode 100644 index 0000000..5f45e97 --- /dev/null +++ b/server/protocols/jmap-integration-testing/memory-jmap-integration-testing/src/test/java/org/apache/james/jmap/memory/MemoryDeletedMessagesVaultTest.java @@ -0,0 +1,50 @@ +/**************************************************************** + * 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.jmap.memory; + +import java.io.IOException; + +import org.apache.james.GuiceJamesServer; +import org.apache.james.MemoryJmapTestRule; +import org.apache.james.jmap.methods.integration.DeletedMessagesVaultTest; +import org.apache.james.mailrepository.api.MailRepositoryUrl; +import org.apache.james.modules.mailbox.PreDeletionHookConfiguration; +import org.apache.james.modules.mailbox.PreDeletionHooksConfiguration; +import org.apache.james.vault.DeletedMessageVaultHook; +import org.apache.james.vault.MailRepositoryDeletedMessageVault; +import org.apache.james.webadmin.WebAdminConfiguration; +import org.junit.Rule; + +public class MemoryDeletedMessagesVaultTest extends DeletedMessagesVaultTest { + + @Rule + public MemoryJmapTestRule memoryJmap = new MemoryJmapTestRule(); + + @Override + protected GuiceJamesServer createJmapServer() throws IOException { + return memoryJmap.jmapServer( + binder -> binder.bind(PreDeletionHooksConfiguration.class) + .toInstance(PreDeletionHooksConfiguration.forHooks( + PreDeletionHookConfiguration.forClass(DeletedMessageVaultHook.class))), + binder -> binder.bind(WebAdminConfiguration.class).toInstance(WebAdminConfiguration.TEST_CONFIGURATION), + binder -> binder.bind(MailRepositoryDeletedMessageVault.Configuration.class) + .toInstance(new MailRepositoryDeletedMessageVault.Configuration(MailRepositoryUrl.from("memory://var/deletedMessages/user")))); + } +} diff --git a/server/protocols/jmap-integration-testing/memory-jmap-integration-testing/src/test/java/org/apache/james/jmap/memory/MemoryFileRepositoryDeletedMessagesVaultTest.java b/server/protocols/jmap-integration-testing/memory-jmap-integration-testing/src/test/java/org/apache/james/jmap/memory/MemoryFileRepositoryDeletedMessagesVaultTest.java new file mode 100644 index 0000000..11f8373 --- /dev/null +++ b/server/protocols/jmap-integration-testing/memory-jmap-integration-testing/src/test/java/org/apache/james/jmap/memory/MemoryFileRepositoryDeletedMessagesVaultTest.java @@ -0,0 +1,50 @@ +/**************************************************************** + * 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.jmap.memory; + +import java.io.IOException; + +import org.apache.james.GuiceJamesServer; +import org.apache.james.MemoryJmapTestRule; +import org.apache.james.jmap.methods.integration.DeletedMessagesVaultTest; +import org.apache.james.mailrepository.api.MailRepositoryUrl; +import org.apache.james.modules.mailbox.PreDeletionHookConfiguration; +import org.apache.james.modules.mailbox.PreDeletionHooksConfiguration; +import org.apache.james.vault.DeletedMessageVaultHook; +import org.apache.james.vault.MailRepositoryDeletedMessageVault; +import org.apache.james.webadmin.WebAdminConfiguration; +import org.junit.Rule; + +public class MemoryFileRepositoryDeletedMessagesVaultTest extends DeletedMessagesVaultTest { + + @Rule + public MemoryJmapTestRule memoryJmap = new MemoryJmapTestRule(); + + @Override + protected GuiceJamesServer createJmapServer() throws IOException { + return memoryJmap.jmapServer( + binder -> binder.bind(PreDeletionHooksConfiguration.class) + .toInstance(PreDeletionHooksConfiguration.forHooks( + PreDeletionHookConfiguration.forClass(DeletedMessageVaultHook.class))), + binder -> binder.bind(WebAdminConfiguration.class).toInstance(WebAdminConfiguration.TEST_CONFIGURATION), + binder -> binder.bind(MailRepositoryDeletedMessageVault.Configuration.class) + .toInstance(new MailRepositoryDeletedMessageVault.Configuration(MailRepositoryUrl.from("file://var/deletedMessages/user")))); + } +} diff --git a/server/protocols/jmap-integration-testing/memory-jmap-integration-testing/src/test/resources/mailrepositorystore.xml b/server/protocols/jmap-integration-testing/memory-jmap-integration-testing/src/test/resources/mailrepositorystore.xml index 3ca4a1d..9dcd6bb 100644 --- a/server/protocols/jmap-integration-testing/memory-jmap-integration-testing/src/test/resources/mailrepositorystore.xml +++ b/server/protocols/jmap-integration-testing/memory-jmap-integration-testing/src/test/resources/mailrepositorystore.xml @@ -28,4 +28,11 @@ <config FIFO="false" CACHEKEYS="true"/> </mailrepository> </mailrepositories> + <mailrepositories> + <mailrepository class="org.apache.james.mailrepository.memory.MemoryMailRepository"> + <protocols> + <protocol>memory</protocol> + </protocols> + </mailrepository> + </mailrepositories> </mailrepositorystore> --------------------------------------------------------------------- To unsubscribe, e-mail: server-dev-unsubscr...@james.apache.org For additional commands, e-mail: server-dev-h...@james.apache.org