You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@james.apache.org by bt...@apache.org on 2021/07/13 09:17:35 UTC

[james-project] 04/05: JAMES-3516 Extract ThreadIdGuessingAlgorithmTest contract

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 f8c179dbca94e79a4c76216458785a0f09f40976
Author: quanth <hq...@linagora.com>
AuthorDate: Tue Jul 6 15:13:48 2021 +0700

    JAMES-3516 Extract ThreadIdGuessingAlgorithmTest contract
---
 .../store/ThreadIdGuessingAlgorithmContract.java   | 205 +++++++++++++++++++++
 1 file changed, 205 insertions(+)

diff --git a/mailbox/store/src/test/java/org/apache/james/mailbox/store/ThreadIdGuessingAlgorithmContract.java b/mailbox/store/src/test/java/org/apache/james/mailbox/store/ThreadIdGuessingAlgorithmContract.java
new file mode 100644
index 0000000..c28757c
--- /dev/null
+++ b/mailbox/store/src/test/java/org/apache/james/mailbox/store/ThreadIdGuessingAlgorithmContract.java
@@ -0,0 +1,205 @@
+/******************************************************************
+ * 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.mailbox.store;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import java.nio.charset.StandardCharsets;
+import java.util.List;
+import java.util.Optional;
+import java.util.stream.Stream;
+
+import org.apache.james.core.Username;
+import org.apache.james.mailbox.MailboxManager;
+import org.apache.james.mailbox.MailboxSession;
+import org.apache.james.mailbox.MessageManager;
+import org.apache.james.mailbox.model.MailboxPath;
+import org.apache.james.mailbox.model.MessageId;
+import org.apache.james.mailbox.model.ThreadId;
+import org.apache.james.mailbox.store.mail.ThreadIdGuessingAlgorithm;
+import org.apache.james.mailbox.store.mail.model.MimeMessageId;
+import org.apache.james.mailbox.store.mail.model.Subject;
+import org.apache.james.mime4j.dom.Message;
+import org.apache.james.mime4j.stream.RawField;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.MethodSource;
+
+public abstract class ThreadIdGuessingAlgorithmContract {
+    public static final Username USER = Username.of("quan");
+    private MailboxManager mailboxManager;
+    private MessageManager inbox;
+    private ThreadIdGuessingAlgorithm testee;
+    private MailboxSession mailboxSession;
+    private CombinationManagerTestSystem testingData;
+    private MessageId newBasedMessageId;
+
+    protected abstract CombinationManagerTestSystem createTestingData();
+
+    protected abstract ThreadIdGuessingAlgorithm initThreadIdGuessingAlgorithm(CombinationManagerTestSystem testingData);
+
+    protected abstract MessageId initNewBasedMessageId();
+
+    @BeforeEach
+    void setUp() throws Exception {
+        testingData = createTestingData();
+        testee = initThreadIdGuessingAlgorithm(testingData);
+        newBasedMessageId = initNewBasedMessageId();
+
+        mailboxManager = testingData.getMailboxManager();
+        mailboxSession = mailboxManager.createSystemSession(USER);
+        mailboxManager.createMailbox(MailboxPath.inbox(USER), mailboxSession);
+        inbox = mailboxManager.getMailbox(MailboxPath.inbox(USER), mailboxSession);
+    }
+
+    @Test
+    void givenNonMailWhenAddAMailThenGuessingThreadIdShouldBasedOnGeneratedMessageId() throws Exception {
+        ThreadId threadId = testee.guessThreadIdReactive(newBasedMessageId, Optional.of(new MimeMessageId("abc")), Optional.empty(), Optional.empty(), Optional.of(new Subject("test")), mailboxSession).block();
+
+        assertThat(threadId.getBaseMessageId()).isEqualTo(newBasedMessageId);
+    }
+
+    private static Stream<Arguments> givenOldMailWhenAddNewRelatedMailsThenGuessingThreadIdShouldReturnSameThreadIdWithOldMail() {
+        return Stream.of(
+            // mails related to old message by subject and Message-ID (but this should not happen in real world cause every mail should have an unique MimeMessageId)
+            Arguments.of(Optional.of(new MimeMessageId("Message-ID")), Optional.empty(), Optional.empty(), Optional.of(new Subject("Re: Test"))),
+            Arguments.of(Optional.of(new MimeMessageId("someInReplyTo")), Optional.empty(), Optional.empty(), Optional.of(new Subject("Re: Test"))),
+            Arguments.of(Optional.of(new MimeMessageId("references1")), Optional.empty(), Optional.empty(), Optional.of(new Subject("Re: Test"))),
+
+            // mails related to old message by subject and In-Reply-To
+            Arguments.of(Optional.empty(), Optional.of(new MimeMessageId("Message-ID")), Optional.empty(), Optional.of(new Subject("Re: Test"))),
+            Arguments.of(Optional.empty(), Optional.of(new MimeMessageId("someInReplyTo")), Optional.empty(), Optional.of(new Subject("Re: Test"))),
+            Arguments.of(Optional.empty(), Optional.of(new MimeMessageId("references2")), Optional.empty(), Optional.of(new Subject("Fwd: Re: Test"))),
+
+            // mails related to old message by subject and References
+            Arguments.of(Optional.empty(), Optional.empty(), Optional.of(List.of(new MimeMessageId("Message-ID"))), Optional.of(new Subject("Fwd: Re: Test"))),
+            Arguments.of(Optional.empty(), Optional.empty(), Optional.of(List.of(new MimeMessageId("someInReplyTo"))), Optional.of(new Subject("Fwd: Re: Test"))),
+            Arguments.of(Optional.empty(), Optional.empty(), Optional.of(List.of(new MimeMessageId("references1"), new MimeMessageId("NonRelated-references2"))), Optional.of(new Subject("Fwd: Re: Test"))),
+            Arguments.of(Optional.empty(), Optional.empty(), Optional.of(List.of(new MimeMessageId("NonRelated-references1"), new MimeMessageId("references2"))), Optional.of(new Subject("Fwd: Re: Test"))),
+            Arguments.of(Optional.empty(), Optional.empty(), Optional.of(List.of(new MimeMessageId("references1"), new MimeMessageId("references2"))), Optional.of(new Subject("Fwd: Re: Test")))
+        );
+    }
+
+    @ParameterizedTest
+    @MethodSource
+    void givenOldMailWhenAddNewRelatedMailsThenGuessingThreadIdShouldReturnSameThreadIdWithOldMail(Optional<MimeMessageId> mimeMessageId, Optional<MimeMessageId> inReplyTo, Optional<List<MimeMessageId>> references, Optional<Subject> subject) throws Exception {
+        // given old mail
+        MessageManager.AppendResult message = inbox.appendMessage(MessageManager.AppendCommand.from(Message.Builder.of()
+            .setSubject("Test")
+            .setMessageId("Message-ID")
+            .setField(new RawField("In-Reply-To", "someInReplyTo"))
+            .addField(new RawField("References", "references1"))
+            .addField(new RawField("References", "references2"))
+            .setBody("testmail", StandardCharsets.UTF_8)), mailboxSession);
+
+        // add new related mails
+        ThreadId threadId = testee.guessThreadIdReactive(newBasedMessageId, mimeMessageId, inReplyTo, references, subject, mailboxSession).block();
+
+        // guessing threadId should return same threadId with old mail
+        assertThat(threadId).isEqualTo(message.getThreadId());
+    }
+
+    private static Stream<Arguments> givenOldMailWhenAddNewMailsWithRelatedSubjectButHaveNonIdenticalMessageIDThenGuessingThreadIdShouldBasedOnGeneratedMessageId() {
+        return Stream.of(
+            // mails related to old message by subject but have non same identical Message-ID
+            Arguments.of(Optional.of(new MimeMessageId("NonRelated-Message-ID")), Optional.empty(), Optional.empty(), Optional.of(new Subject("Re: Test"))),
+            Arguments.of(Optional.empty(), Optional.of(new MimeMessageId("NonRelated-someInReplyTo")), Optional.empty(), Optional.of(new Subject("Re: Test"))),
+            Arguments.of(Optional.empty(), Optional.empty(), Optional.of(List.of(new MimeMessageId("NonRelated-references1"), new MimeMessageId("NonRelated-references2"))), Optional.of(new Subject("Re: Test")))
+        );
+    }
+
+    @ParameterizedTest
+    @MethodSource
+    void givenOldMailWhenAddNewMailsWithRelatedSubjectButHaveNonIdenticalMessageIDThenGuessingThreadIdShouldBasedOnGeneratedMessageId(Optional<MimeMessageId> mimeMessageId, Optional<MimeMessageId> inReplyTo, Optional<List<MimeMessageId>> references, Optional<Subject> subject) throws Exception {
+        // given old mail
+        MessageManager.AppendResult message = inbox.appendMessage(MessageManager.AppendCommand.from(Message.Builder.of()
+            .setSubject("Test")
+            .setMessageId("Message-ID")
+            .setField(new RawField("In-Reply-To", "someInReplyTo"))
+            .addField(new RawField("References", "references1"))
+            .addField(new RawField("References", "references2"))
+            .setBody("testmail", StandardCharsets.UTF_8)), mailboxSession);
+
+        // add mails related to old message by subject but have non same identical Message-ID
+        ThreadId threadId = testee.guessThreadIdReactive(newBasedMessageId, mimeMessageId, inReplyTo, references, subject, mailboxSession).block();
+
+        // guessing threadId should based on generated MessageId
+        assertThat(threadId.getBaseMessageId()).isEqualTo(newBasedMessageId);
+    }
+
+    private static Stream<Arguments> givenOldMailWhenAddNewMailsWithNonRelatedSubjectButHaveSameIdenticalMessageIDThenGuessingThreadIdShouldBasedOnGeneratedMessageId() {
+        return Stream.of(
+            // mails related to old message by having identical Message-ID but non related subject
+            Arguments.of(Optional.of(new MimeMessageId("Message-ID")), Optional.empty(), Optional.empty(), Optional.of(new Subject("NonRelated-Subject"))),
+            Arguments.of(Optional.empty(), Optional.of(new MimeMessageId("someInReplyTo")), Optional.empty(), Optional.of(new Subject("NonRelated-Subject"))),
+            Arguments.of(Optional.empty(), Optional.empty(), Optional.of(List.of(new MimeMessageId("references1"), new MimeMessageId("references2"))), Optional.of(new Subject("NonRelated-Subject")))
+        );
+    }
+
+    @ParameterizedTest
+    @MethodSource
+    void givenOldMailWhenAddNewMailsWithNonRelatedSubjectButHaveSameIdenticalMessageIDThenGuessingThreadIdShouldBasedOnGeneratedMessageId(Optional<MimeMessageId> mimeMessageId, Optional<MimeMessageId> inReplyTo, Optional<List<MimeMessageId>> references, Optional<Subject> subject) throws Exception {
+        // given old mail
+        MessageManager.AppendResult message = inbox.appendMessage(MessageManager.AppendCommand.from(Message.Builder.of()
+            .setSubject("Test")
+            .setMessageId("Message-ID")
+            .setField(new RawField("In-Reply-To", "someInReplyTo"))
+            .addField(new RawField("References", "references1"))
+            .addField(new RawField("References", "references2"))
+            .setBody("testmail", StandardCharsets.UTF_8)), mailboxSession);
+
+        // add mails related to old message by having identical Message-ID but non related subject
+        ThreadId threadId = testee.guessThreadIdReactive(newBasedMessageId, mimeMessageId, inReplyTo, references, subject, mailboxSession).block();
+
+        // guess ThreadId should based on generated MessageId
+        assertThat(threadId.getBaseMessageId()).isEqualTo(newBasedMessageId);
+    }
+
+    private static Stream<Arguments> givenOldMailWhenAddNonRelatedMailsThenGuessingThreadIdShouldBasedOnGeneratedMessageId() {
+        return Stream.of(
+            // mails non related to old message by both subject and identical Message-ID
+            Arguments.of(Optional.of(new MimeMessageId("NonRelated-Message-ID")), Optional.empty(), Optional.empty(), Optional.of(new Subject("NonRelated-Subject"))),
+            Arguments.of(Optional.empty(), Optional.of(new MimeMessageId("NonRelated-someInReplyTo")), Optional.empty(), Optional.of(new Subject("NonRelated-Subject"))),
+            Arguments.of(Optional.empty(), Optional.empty(), Optional.of(List.of(new MimeMessageId("NonRelated-references1"), new MimeMessageId("NonRelated-references2"))), Optional.of(new Subject("NonRelated-Subject")))
+        );
+    }
+
+    @ParameterizedTest
+    @MethodSource
+    void givenOldMailWhenAddNonRelatedMailsThenGuessingThreadIdShouldBasedOnGeneratedMessageId(Optional<MimeMessageId> mimeMessageId, Optional<MimeMessageId> inReplyTo, Optional<List<MimeMessageId>> references, Optional<Subject> subject) throws Exception {
+        // given old mail
+        MessageManager.AppendResult message = inbox.appendMessage(MessageManager.AppendCommand.from(Message.Builder.of()
+            .setSubject("Test")
+            .setMessageId("Message-ID")
+            .setField(new RawField("In-Reply-To", "someInReplyTo"))
+            .addField(new RawField("References", "references1"))
+            .addField(new RawField("References", "references2"))
+            .setBody("testmail", StandardCharsets.UTF_8)), mailboxSession);
+
+        // add mails non related to old message by both subject and identical Message-ID
+        ThreadId threadId = testee.guessThreadIdReactive(newBasedMessageId, mimeMessageId, inReplyTo, references, subject, mailboxSession).block();
+
+        // guess ThreadId should based on generatedMessageId
+        assertThat(threadId.getBaseMessageId()).isEqualTo(newBasedMessageId);
+    }
+
+}

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