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