This is an automated email from the ASF dual-hosted git repository. chibenwa pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/james-project.git
commit 51829a1cd533689491b88708c4a1b48f2750f0c9 Author: Quan Tran <[email protected]> AuthorDate: Mon Jul 13 22:58:40 2026 +0700 [BUILD] ThreadGetContract: isolate using different users --- .../DistributedThreadGetMethodTest.java | 13 ++-- .../jmap/rfc8621/contract/ThreadGetContract.scala | 84 +++++++++++++--------- .../rfc8621/memory/MemoryThreadGetMethodTest.java | 2 +- .../rfc8621/postgres/PostgresThreadGetTest.java | 1 + 4 files changed, 60 insertions(+), 40 deletions(-) diff --git a/server/protocols/jmap-rfc-8621-integration-tests/distributed-jmap-rfc-8621-integration-tests/src/test/java/org/apache/james/jmap/rfc8621/distributed/DistributedThreadGetMethodTest.java b/server/protocols/jmap-rfc-8621-integration-tests/distributed-jmap-rfc-8621-integration-tests/src/test/java/org/apache/james/jmap/rfc8621/distributed/DistributedThreadGetMethodTest.java index 6796723093..0f5b106ce1 100644 --- a/server/protocols/jmap-rfc-8621-integration-tests/distributed-jmap-rfc-8621-integration-tests/src/test/java/org/apache/james/jmap/rfc8621/distributed/DistributedThreadGetMethodTest.java +++ b/server/protocols/jmap-rfc-8621-integration-tests/distributed-jmap-rfc-8621-integration-tests/src/test/java/org/apache/james/jmap/rfc8621/distributed/DistributedThreadGetMethodTest.java @@ -58,14 +58,11 @@ public class DistributedThreadGetMethodTest implements ThreadGetContract { .and().pollDelay(ONE_HUNDRED_MILLISECONDS) .await(); - private final QueryConverter queryConverter = new QueryConverter(new DefaultCriterionConverter()); - private ReactorOpenSearchClient client; - @RegisterExtension - org.apache.james.backends.opensearch.DockerOpenSearchExtension openSearch = new org.apache.james.backends.opensearch.DockerOpenSearchExtension(); + static org.apache.james.backends.opensearch.DockerOpenSearchExtension openSearch = new org.apache.james.backends.opensearch.DockerOpenSearchExtension(); @RegisterExtension - JamesServerExtension testExtension = new JamesServerBuilder<CassandraRabbitMQJamesConfiguration>(tmpDir -> + static JamesServerExtension testExtension = new JamesServerBuilder<CassandraRabbitMQJamesConfiguration>(tmpDir -> CassandraRabbitMQJamesConfiguration.builder() .workingDirectory(tmpDir) .configurationFromClasspath() @@ -82,8 +79,12 @@ public class DistributedThreadGetMethodTest implements ThreadGetContract { .extension(new AwsS3BlobStoreExtension()) .server(configuration -> CassandraRabbitMQJamesServerMain.createServer(configuration) .overrideWith(new TestJMAPServerModule())) + .lifeCycle(JamesServerExtension.Lifecycle.PER_CLASS) .build(); + private final QueryConverter queryConverter = new QueryConverter(new DefaultCriterionConverter()); + private ReactorOpenSearchClient client; + @AfterEach void tearDown() throws IOException { client.close(); @@ -111,4 +112,4 @@ public class DistributedThreadGetMethodTest implements ThreadGetContract { .block() .hits().total().value()).isEqualTo(totalHits)); } -} \ No newline at end of file +} diff --git a/server/protocols/jmap-rfc-8621-integration-tests/jmap-rfc-8621-integration-tests-common/src/main/scala/org/apache/james/jmap/rfc8621/contract/ThreadGetContract.scala b/server/protocols/jmap-rfc-8621-integration-tests/jmap-rfc-8621-integration-tests-common/src/main/scala/org/apache/james/jmap/rfc8621/contract/ThreadGetContract.scala index aca417bcb3..8610e87d0d 100644 --- a/server/protocols/jmap-rfc-8621-integration-tests/jmap-rfc-8621-integration-tests-common/src/main/scala/org/apache/james/jmap/rfc8621/contract/ThreadGetContract.scala +++ b/server/protocols/jmap-rfc-8621-integration-tests/jmap-rfc-8621-integration-tests-common/src/main/scala/org/apache/james/jmap/rfc8621/contract/ThreadGetContract.scala @@ -21,17 +21,20 @@ package org.apache.james.jmap.rfc8621.contract import java.nio.charset.StandardCharsets import java.util +import java.util.UUID import com.google.common.collect.ImmutableList +import com.google.common.hash.Hashing import io.netty.handler.codec.http.HttpHeaderNames.ACCEPT import io.restassured.RestAssured.{`given`, requestSpecification} import io.restassured.http.ContentType.JSON import net.javacrumbs.jsonunit.assertj.JsonAssertions.assertThatJson import org.apache.http.HttpStatus.SC_OK import org.apache.james.GuiceJamesServer +import org.apache.james.core.Username import org.apache.james.jmap.core.ResponseObject.SESSION_STATE import org.apache.james.jmap.http.UserCredential -import org.apache.james.jmap.rfc8621.contract.Fixture.{ACCEPT_RFC8621_VERSION_HEADER, BOB, BOB_PASSWORD, DOMAIN, authScheme, baseRequestSpecBuilder} +import org.apache.james.jmap.rfc8621.contract.Fixture.{ACCEPT_RFC8621_VERSION_HEADER, BOB_PASSWORD, DOMAIN, authScheme, baseRequestSpecBuilder} import org.apache.james.mailbox.MessageManager import org.apache.james.mailbox.model.{MailboxId, MailboxPath, SearchQuery} import org.apache.james.mime4j.dom.Message @@ -40,7 +43,19 @@ import org.apache.james.modules.MailboxProbeImpl import org.apache.james.utils.DataProbeImpl import org.junit.jupiter.api.{BeforeEach, Test} +object ThreadGetContract { + case class TestContext(bobUsername: Username, bobAccountId: String) + val currentContext: java.util.concurrent.atomic.AtomicReference[TestContext] = new java.util.concurrent.atomic.AtomicReference[TestContext]() +} + trait ThreadGetContract { + import ThreadGetContract.currentContext + + def bobUsername: Username = currentContext.get().bobUsername + def bobAccountId: String = currentContext.get().bobAccountId + + private def accountId(username: Username): String = + Hashing.sha256().hashString(username.asString(), StandardCharsets.UTF_8).toString protected def awaitMessageCount(mailboxIds: util.List[MailboxId], query: SearchQuery, messageCount: Long): Unit @@ -49,15 +64,18 @@ trait ThreadGetContract { @BeforeEach def setUp(server: GuiceJamesServer): Unit = { initOpenSearchClient() + val uniqueSuffix = UUID.randomUUID().toString.replace("-", "").take(8) + val bob = Username.fromLocalPartWithDomain(s"bob$uniqueSuffix", DOMAIN) + currentContext.set(ThreadGetContract.TestContext(bob, accountId(bob))) server.getProbe(classOf[DataProbeImpl]) .fluent .addDomain(DOMAIN.asString) .addDomain("domain-alias.tld") - .addUser(BOB.asString, BOB_PASSWORD) + .addUser(bobUsername.asString, BOB_PASSWORD) requestSpecification = baseRequestSpecBuilder(server) - .setAuth(authScheme(UserCredential(BOB, BOB_PASSWORD))) + .setAuth(authScheme(UserCredential(bobUsername, BOB_PASSWORD))) .build } @@ -69,7 +87,7 @@ trait ThreadGetContract { | "methodCalls": [[ | "Thread/get", | { - | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6", + | "accountId": "$bobAccountId", | "ids": ["123456"] | }, | "c1"]] @@ -95,7 +113,7 @@ trait ThreadGetContract { | [ | "Thread/get", | { - | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6", + | "accountId": "$bobAccountId", | "state": "2c9f1b12-b35a-43e6-9af2-0106fb53a943", | "list": [ | @@ -154,12 +172,12 @@ trait ThreadGetContract { @Test def addRelatedMailsInAThreadThenGetThatThreadShouldReturnExactThreadObjectWithEmailIdsSortedByArrivalDate(server: GuiceJamesServer): Unit = { - val bobPath = MailboxPath.inbox(BOB) + val bobPath = MailboxPath.inbox(bobUsername) server.getProbe(classOf[MailboxProbeImpl]).createMailbox(bobPath) // given 3 mails with related Subject and related Mime Message-ID fields val message1: MessageManager.AppendResult = server.getProbe(classOf[MailboxProbeImpl]) - .appendMessageAndGetAppendResult(BOB.asString(), bobPath, + .appendMessageAndGetAppendResult(bobUsername.asString(), bobPath, MessageManager.AppendCommand.from(Message.Builder.of.setSubject("Test") .setMessageId("Message-ID-1") .setBody("testmail", StandardCharsets.UTF_8))) @@ -167,7 +185,7 @@ trait ThreadGetContract { // message2 reply to message1 val message2: MessageManager.AppendResult = server.getProbe(classOf[MailboxProbeImpl]) - .appendMessageAndGetAppendResult(BOB.asString(), bobPath, + .appendMessageAndGetAppendResult(bobUsername.asString(), bobPath, MessageManager.AppendCommand.from(Message.Builder.of.setSubject("Re: Test") .setMessageId("Message-ID-2") .setField(new RawField("In-Reply-To", "Message-ID-1")) @@ -176,7 +194,7 @@ trait ThreadGetContract { // message3 related to message1 through Subject and References message1's Message-ID val message3: MessageManager.AppendResult = server.getProbe(classOf[MailboxProbeImpl]) - .appendMessageAndGetAppendResult(BOB.asString(), bobPath, + .appendMessageAndGetAppendResult(bobUsername.asString(), bobPath, MessageManager.AppendCommand.from(Message.Builder.of.setSubject("Fwd: Re: Test") .setMessageId("Message-ID-3") .setField(new RawField("In-Reply-To", "Random-InReplyTo")) @@ -196,7 +214,7 @@ trait ThreadGetContract { | "methodCalls": [[ | "Thread/get", | { - | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6", + | "accountId": "$bobAccountId", | "ids": ["$threadId"] | }, | "c1"]] @@ -222,7 +240,7 @@ trait ThreadGetContract { | [ | "Thread/get", | { - | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6", + | "accountId": "$bobAccountId", | "state": "2c9f1b12-b35a-43e6-9af2-0106fb53a943", | "list": [{ | "id": "$threadId", @@ -240,12 +258,12 @@ trait ThreadGetContract { @Test def givenTwoThreadGetThatTwoThreadShouldReturnExactTwoThreadObjectWithEmailIdsSortedByArrivalDate(server: GuiceJamesServer): Unit = { - val bobPath = MailboxPath.inbox(BOB) + val bobPath = MailboxPath.inbox(bobUsername) server.getProbe(classOf[MailboxProbeImpl]).createMailbox(bobPath) // given 2 mails with related Subject and related Mime Message-ID fields in threadA val message1: MessageManager.AppendResult = server.getProbe(classOf[MailboxProbeImpl]) - .appendMessageAndGetAppendResult(BOB.asString(), bobPath, + .appendMessageAndGetAppendResult(bobUsername.asString(), bobPath, MessageManager.AppendCommand.from(Message.Builder.of.setSubject("Test") .setMessageId("Message-ID-1") .setBody("testmail", StandardCharsets.UTF_8))) @@ -253,7 +271,7 @@ trait ThreadGetContract { // message2 reply to message1 val message2: MessageManager.AppendResult = server.getProbe(classOf[MailboxProbeImpl]) - .appendMessageAndGetAppendResult(BOB.asString(), bobPath, + .appendMessageAndGetAppendResult(bobUsername.asString(), bobPath, MessageManager.AppendCommand.from(Message.Builder.of.setSubject("Re: Test") .setMessageId("Message-ID-2") .setField(new RawField("In-Reply-To", "Message-ID-1")) @@ -262,7 +280,7 @@ trait ThreadGetContract { // message3 in threadB val message3: MessageManager.AppendResult = server.getProbe(classOf[MailboxProbeImpl]) - .appendMessageAndGetAppendResult(BOB.asString(), bobPath, + .appendMessageAndGetAppendResult(bobUsername.asString(), bobPath, MessageManager.AppendCommand.from(Message.Builder.of.setSubject("Message3-SubjectLine") .setMessageId("Message-ID-3") .setBody("testmail", StandardCharsets.UTF_8))) @@ -280,7 +298,7 @@ trait ThreadGetContract { | "methodCalls": [[ | "Thread/get", | { - | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6", + | "accountId": "$bobAccountId", | "ids": ["$threadA", "$threadB"] | }, | "c1"]] @@ -308,18 +326,18 @@ trait ThreadGetContract { @Test def givenOneThreadGetTwoThreadShouldReturnOnlyOneThreadObjectAndNotFound(server: GuiceJamesServer): Unit = { - val bobPath = MailboxPath.inbox(BOB) + val bobPath = MailboxPath.inbox(bobUsername) server.getProbe(classOf[MailboxProbeImpl]).createMailbox(bobPath) // given 2 mails with related Subject and related Mime Message-ID fields in threadA val message1: MessageManager.AppendResult = server.getProbe(classOf[MailboxProbeImpl]) - .appendMessageAndGetAppendResult(BOB.asString(), bobPath, + .appendMessageAndGetAppendResult(bobUsername.asString(), bobPath, MessageManager.AppendCommand.from(Message.Builder.of.setSubject("Test") .setMessageId("Message-ID-1") .setBody("testmail", StandardCharsets.UTF_8))) // message2 reply to message1 val message2: MessageManager.AppendResult = server.getProbe(classOf[MailboxProbeImpl]) - .appendMessageAndGetAppendResult(BOB.asString(), bobPath, + .appendMessageAndGetAppendResult(bobUsername.asString(), bobPath, MessageManager.AppendCommand.from(Message.Builder.of.setSubject("Re: Test") .setMessageId("Message-ID-2") .setField(new RawField("In-Reply-To", "Message-ID-1")) @@ -337,7 +355,7 @@ trait ThreadGetContract { | "methodCalls": [[ | "Thread/get", | { - | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6", + | "accountId": "$bobAccountId", | "ids": ["$threadA", "nonExistThread"] | }, | "c1"]] @@ -363,7 +381,7 @@ trait ThreadGetContract { | [ | "Thread/get", | { - | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6", + | "accountId": "$bobAccountId", | "state": "2c9f1b12-b35a-43e6-9af2-0106fb53a943", | "list": [{ | "id": "$threadA", @@ -384,18 +402,18 @@ trait ThreadGetContract { @Test def addThreeMailsWithRelatedSubjectButNonIdenticalMimeMessageIDThenGetThatThreadShouldNotReturnUnrelatedMails(server: GuiceJamesServer): Unit = { - val bobPath = MailboxPath.inbox(BOB) + val bobPath = MailboxPath.inbox(bobUsername) server.getProbe(classOf[MailboxProbeImpl]).createMailbox(bobPath) val message1: MessageManager.AppendResult = server.getProbe(classOf[MailboxProbeImpl]) - .appendMessageAndGetAppendResult(BOB.asString(), bobPath, + .appendMessageAndGetAppendResult(bobUsername.asString(), bobPath, MessageManager.AppendCommand.from(Message.Builder.of.setSubject("Test") .setMessageId("Message-ID-1") .setBody("testmail", StandardCharsets.UTF_8))) // message2 have related subject with message1 but non identical Mime Message-ID val message2: MessageManager.AppendResult = server.getProbe(classOf[MailboxProbeImpl]) - .appendMessageAndGetAppendResult(BOB.asString(), bobPath, + .appendMessageAndGetAppendResult(bobUsername.asString(), bobPath, MessageManager.AppendCommand.from(Message.Builder.of.setSubject("Re: Test") .setMessageId("Message-ID-2") .setField(new RawField("In-Reply-To", "Random-InReplyTo")) @@ -403,7 +421,7 @@ trait ThreadGetContract { // message3 have related subject with message1 but non identical Mime Message-ID val message3: MessageManager.AppendResult = server.getProbe(classOf[MailboxProbeImpl]) - .appendMessageAndGetAppendResult(BOB.asString(), bobPath, + .appendMessageAndGetAppendResult(bobUsername.asString(), bobPath, MessageManager.AppendCommand.from(Message.Builder.of.setSubject("Fwd: Re: Test") .setMessageId("Message-ID-3") .setField(new RawField("In-Reply-To", "Another-Random-InReplyTo")) @@ -421,7 +439,7 @@ trait ThreadGetContract { | "methodCalls": [[ | "Thread/get", | { - | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6", + | "accountId": "$bobAccountId", | "ids": ["$threadId1"] | }, | "c1"]] @@ -447,7 +465,7 @@ trait ThreadGetContract { | [ | "Thread/get", | { - | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6", + | "accountId": "$bobAccountId", | "state": "2c9f1b12-b35a-43e6-9af2-0106fb53a943", | "list": [{ | "id": "$threadId1", @@ -465,18 +483,18 @@ trait ThreadGetContract { @Test def addThreeMailsWithIdenticalMimeMessageIDButNonRelatedSubjectThenGetThatThreadShouldNotReturnUnrelatedMails(server: GuiceJamesServer): Unit = { - val bobPath = MailboxPath.inbox(BOB) + val bobPath = MailboxPath.inbox(bobUsername) server.getProbe(classOf[MailboxProbeImpl]).createMailbox(bobPath) val message1: MessageManager.AppendResult = server.getProbe(classOf[MailboxProbeImpl]) - .appendMessageAndGetAppendResult(BOB.asString(), bobPath, + .appendMessageAndGetAppendResult(bobUsername.asString(), bobPath, MessageManager.AppendCommand.from(Message.Builder.of.setSubject("Test1") .setMessageId("Message-ID-1") .setBody("testmail", StandardCharsets.UTF_8))) // message2 have identical Mime Message-ID with message1 through In-Reply-To field but have non related subject val message2: MessageManager.AppendResult = server.getProbe(classOf[MailboxProbeImpl]) - .appendMessageAndGetAppendResult(BOB.asString(), bobPath, + .appendMessageAndGetAppendResult(bobUsername.asString(), bobPath, MessageManager.AppendCommand.from(Message.Builder.of.setSubject("Test2") .setMessageId("Message-ID-2") .setField(new RawField("In-Reply-To", "Message-ID-1")) @@ -484,7 +502,7 @@ trait ThreadGetContract { // message2 have identical Mime Message-ID with message1 through References field but have non related subject val message3: MessageManager.AppendResult = server.getProbe(classOf[MailboxProbeImpl]) - .appendMessageAndGetAppendResult(BOB.asString(), bobPath, + .appendMessageAndGetAppendResult(bobUsername.asString(), bobPath, MessageManager.AppendCommand.from(Message.Builder.of.setSubject("Test3") .setMessageId("Message-ID-3") .setField(new RawField("In-Reply-To", "Random-InReplyTo")) @@ -502,7 +520,7 @@ trait ThreadGetContract { | "methodCalls": [[ | "Thread/get", | { - | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6", + | "accountId": "$bobAccountId", | "ids": ["$threadId1"] | }, | "c1"]] @@ -528,7 +546,7 @@ trait ThreadGetContract { | [ | "Thread/get", | { - | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6", + | "accountId": "$bobAccountId", | "state": "2c9f1b12-b35a-43e6-9af2-0106fb53a943", | "list": [{ | "id": "$threadId1", diff --git a/server/protocols/jmap-rfc-8621-integration-tests/memory-jmap-rfc-8621-integration-tests/src/test/java/org/apache/james/jmap/rfc8621/memory/MemoryThreadGetMethodTest.java b/server/protocols/jmap-rfc-8621-integration-tests/memory-jmap-rfc-8621-integration-tests/src/test/java/org/apache/james/jmap/rfc8621/memory/MemoryThreadGetMethodTest.java index 6e438a39a7..9ea83b9b62 100644 --- a/server/protocols/jmap-rfc-8621-integration-tests/memory-jmap-rfc-8621-integration-tests/src/test/java/org/apache/james/jmap/rfc8621/memory/MemoryThreadGetMethodTest.java +++ b/server/protocols/jmap-rfc-8621-integration-tests/memory-jmap-rfc-8621-integration-tests/src/test/java/org/apache/james/jmap/rfc8621/memory/MemoryThreadGetMethodTest.java @@ -25,7 +25,7 @@ import org.apache.james.jmap.rfc8621.contract.ThreadGetContract; import org.apache.james.mailbox.model.MailboxId; import org.apache.james.mailbox.model.SearchQuery; -public class MemoryThreadGetMethodTest extends MemoryBase implements ThreadGetContract { +public class MemoryThreadGetMethodTest extends PerClassMemoryBase implements ThreadGetContract { @Override public void awaitMessageCount(List<MailboxId> mailboxIds, SearchQuery query, long messageCount) { diff --git a/server/protocols/jmap-rfc-8621-integration-tests/postgres-jmap-rfc-8621-integration-tests/src/test/java/org/apache/james/jmap/rfc8621/postgres/PostgresThreadGetTest.java b/server/protocols/jmap-rfc-8621-integration-tests/postgres-jmap-rfc-8621-integration-tests/src/test/java/org/apache/james/jmap/rfc8621/postgres/PostgresThreadGetTest.java index e643c5419a..c09db7a878 100644 --- a/server/protocols/jmap-rfc-8621-integration-tests/postgres-jmap-rfc-8621-integration-tests/src/test/java/org/apache/james/jmap/rfc8621/postgres/PostgresThreadGetTest.java +++ b/server/protocols/jmap-rfc-8621-integration-tests/postgres-jmap-rfc-8621-integration-tests/src/test/java/org/apache/james/jmap/rfc8621/postgres/PostgresThreadGetTest.java @@ -58,6 +58,7 @@ public class PostgresThreadGetTest implements ThreadGetContract { .extension(new DockerOpenSearchExtension()) .server(configuration -> PostgresJamesServerMain.createServer(configuration) .overrideWith(new TestJMAPServerModule())) + .lifeCycle(JamesServerExtension.Lifecycle.PER_CLASS) .build(); @Override --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
