You are viewing a plain text version of this content. The canonical link for it is here.
Posted to server-dev@james.apache.org by bt...@apache.org on 2019/12/13 10:01:22 UTC

[james-project] 17/17: [JAMES-3001] make sure spamassassin learning is done before going ahead with next steps

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 bfeb346a3880bf775af653c4e7bbf999041c0604
Author: Matthieu Baechler <ma...@apache.org>
AuthorDate: Fri Dec 6 09:43:20 2019 +0100

    [JAMES-3001] make sure spamassassin learning is done before going ahead with next steps
    
    	Mails can be seen from IMAP/JMAP perspective before all listeners
    	got called because mail delivery + listeners is not an atomic
    	operation.
    
    	In production it's not a problem but in tests it can make tests
    	fail. For example with SpamAssassin the learning of moving a
    	mail can win the race with the learning of delivering it to
    	a specific mailbox, inverted the expected order of events.
---
 .../methods/integration/SpamAssassinContract.java   | 21 ++++++++++++++++++++-
 1 file changed, 20 insertions(+), 1 deletion(-)

diff --git a/server/protocols/jmap-draft-integration-testing/jmap-draft-integration-testing-common/src/test/java/org/apache/james/jmap/draft/methods/integration/SpamAssassinContract.java b/server/protocols/jmap-draft-integration-testing/jmap-draft-integration-testing-common/src/test/java/org/apache/james/jmap/draft/methods/integration/SpamAssassinContract.java
index 1ff74ab..cabc051 100644
--- a/server/protocols/jmap-draft-integration-testing/jmap-draft-integration-testing-common/src/test/java/org/apache/james/jmap/draft/methods/integration/SpamAssassinContract.java
+++ b/server/protocols/jmap-draft-integration-testing/jmap-draft-integration-testing-common/src/test/java/org/apache/james/jmap/draft/methods/integration/SpamAssassinContract.java
@@ -29,6 +29,7 @@ import static org.apache.james.jmap.TestingConstants.ARGUMENTS;
 import static org.apache.james.jmap.TestingConstants.LOCALHOST_IP;
 import static org.apache.james.jmap.TestingConstants.NAME;
 import static org.apache.james.jmap.TestingConstants.calmlyAwait;
+import static org.assertj.core.api.Assertions.assertThat;
 import static org.hamcrest.Matchers.equalTo;
 import static org.hamcrest.Matchers.hasSize;
 
@@ -45,6 +46,7 @@ import org.apache.james.modules.protocols.ImapGuiceProbe;
 import org.apache.james.spamassassin.SpamAssassinExtension;
 import org.apache.james.utils.DataProbeImpl;
 import org.apache.james.utils.IMAPMessageReader;
+import org.apache.james.utils.SpoolerProbe;
 import org.awaitility.Duration;
 import org.junit.jupiter.api.AfterEach;
 import org.junit.jupiter.api.BeforeEach;
@@ -86,7 +88,8 @@ public interface SpamAssassinContract {
     }
 
     @AfterEach
-    default void tearDown(SpamAssassinExtension.SpamAssassin spamAssassin) throws Exception {
+    default void tearDown(SpamAssassinExtension.SpamAssassin spamAssassin, GuiceJamesServer jamesServer) throws Exception {
+        calmlyAwait.atMost(Duration.ONE_MINUTE).untilAsserted(() -> assertEveryListenerGotCalled(jamesServer));
         spamAssassin.clear(ALICE);
     }
 
@@ -109,7 +112,9 @@ public interface SpamAssassinContract {
             .body(setMessageCreate(bobAccessToken))
         .when()
             .post("/jmap");
+
         calmlyAwait.atMost(Duration.ONE_MINUTE).untilAsserted(() -> assertMessagesFoundInMailbox(aliceAccessToken, getInboxId(aliceAccessToken), 1));
+        calmlyAwait.atMost(Duration.ONE_MINUTE).untilAsserted(() -> assertEveryListenerGotCalled(jamesServer));
 
         // Alice is moving this message to Spam -> learning in SpamAssassin
         List<String> messageIds = with()
@@ -161,6 +166,8 @@ public interface SpamAssassinContract {
         .when()
             .post("/jmap");
         calmlyAwait.atMost(Duration.ONE_MINUTE).untilAsserted(() -> assertMessagesFoundInMailbox(aliceAccessToken, getInboxId(aliceAccessToken), 1));
+        calmlyAwait.atMost(Duration.ONE_MINUTE).untilAsserted(() -> assertEveryListenerGotCalled(jamesServer));
+
 
         // Alice is copying this message to Spam -> learning in SpamAssassin
         try (IMAPMessageReader imapMessageReader = new IMAPMessageReader()) {
@@ -197,6 +204,7 @@ public interface SpamAssassinContract {
         .when()
             .post("/jmap");
         calmlyAwait.atMost(Duration.ONE_MINUTE).untilAsserted(() -> assertMessagesFoundInMailbox(aliceAccessToken, getInboxId(aliceAccessToken), 1));
+        calmlyAwait.atMost(Duration.ONE_MINUTE).untilAsserted(() -> assertEveryListenerGotCalled(jamesServer));
 
         try (IMAPMessageReader imapMessageReader = new IMAPMessageReader()) {
             imapMessageReader.connect(LOCALHOST_IP, jamesServer.getProbe(ImapGuiceProbe.class).getImapPort())
@@ -232,6 +240,7 @@ public interface SpamAssassinContract {
             .when()
             .post("/jmap");
         calmlyAwait.atMost(Duration.ONE_MINUTE).untilAsserted(() -> assertMessagesFoundInMailbox(aliceAccessToken, getInboxId(aliceAccessToken), 1));
+        calmlyAwait.atMost(Duration.ONE_MINUTE).untilAsserted(() -> assertEveryListenerGotCalled(jamesServer));
 
         // Alice is moving this message to Spam -> learning in SpamAssassin
         List<String> messageIds = with()
@@ -296,6 +305,7 @@ public interface SpamAssassinContract {
             .when()
             .post("/jmap");
         calmlyAwait.atMost(Duration.ONE_MINUTE).untilAsserted(() -> assertMessagesFoundInMailbox(aliceAccessToken, getInboxId(aliceAccessToken), 1));
+        calmlyAwait.atMost(Duration.ONE_MINUTE).untilAsserted(() -> assertEveryListenerGotCalled(jamesServer));
 
         // Alice is moving this message to Spam -> learning in SpamAssassin
         List<String> messageIds = with()
@@ -360,6 +370,7 @@ public interface SpamAssassinContract {
             .when()
             .post("/jmap");
         calmlyAwait.atMost(Duration.ONE_MINUTE).untilAsserted(() -> assertMessagesFoundInMailbox(aliceAccessToken, getInboxId(aliceAccessToken), 1));
+        calmlyAwait.atMost(Duration.ONE_MINUTE).untilAsserted(() -> assertEveryListenerGotCalled(jamesServer));
 
         // Alice is moving this message to Spam -> learning in SpamAssassin
         List<String> messageIds = with()
@@ -421,6 +432,7 @@ public interface SpamAssassinContract {
             .when()
             .post("/jmap");
         calmlyAwait.atMost(Duration.ONE_MINUTE).untilAsserted(() -> assertMessagesFoundInMailbox(aliceAccessToken, getInboxId(aliceAccessToken), 1));
+        calmlyAwait.atMost(Duration.ONE_MINUTE).untilAsserted(() -> assertEveryListenerGotCalled(jamesServer));
 
         // Alice is moving this message to Spam -> learning in SpamAssassin
         List<String> messageIds = with()
@@ -483,6 +495,7 @@ public interface SpamAssassinContract {
             .when()
             .post("/jmap");
         calmlyAwait.atMost(Duration.ONE_MINUTE).untilAsserted(() -> assertMessagesFoundInMailbox(aliceAccessToken, getInboxId(aliceAccessToken), 1));
+        calmlyAwait.atMost(Duration.ONE_MINUTE).untilAsserted(() -> assertEveryListenerGotCalled(jamesServer));
 
         // Alice is moving this message to Spam -> learning in SpamAssassin
         List<String> messageIds = with()
@@ -672,4 +685,10 @@ public interface SpamAssassinContract {
     default String getTrashId(AccessToken accessToken) {
         return getMailboxId(accessToken, Role.TRASH);
     }
+
+    default void assertEveryListenerGotCalled(GuiceJamesServer jamesServer) {
+        assertThat(jamesServer.getProbe(SpoolerProbe.class).processingFinished())
+            .describedAs("waiting that every listener get called")
+            .isTrue();
+    }
 }


---------------------------------------------------------------------
To unsubscribe, e-mail: server-dev-unsubscribe@james.apache.org
For additional commands, e-mail: server-dev-help@james.apache.org