You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@james.apache.org by rc...@apache.org on 2021/01/14 03:26:05 UTC
[james-project] branch master updated (6d899ce -> b929cdb)
This is an automated email from the ASF dual-hosted git repository.
rcordier pushed a change to branch master
in repository https://gitbox.apache.org/repos/asf/james-project.git.
from 6d899ce JAMES-2543 Junit 4 -> 5 public access modifier cleanups
new c2cd494 JAMES-3436 Email/set method contract fix up
new 5acfb98 JAMES-3436 Email/set create should reject headers properties
new ac22a26 JAMES-3474 Email/set should handle state property
new 716b303 JAMES-3474 New/old state should be ignored in irrelevant Email/set calls
new c4d9933 JAMES-3474 Disable asynchronous state tests for distributed environment
new 0c6015b JAMES-3470 CassandraEmailChangeRepository implementation
new fcc9ef9 JAMES-3470 Binding for CassandraEmailChangeModule
new 4c16e1f JAMES-3470 EmailChangeRepositoryContract should stop relying on TestMessageId
new 5de9000 JAMES-3470 Adapt Email/set test for more stability
new a046adf JAMES-3472 Remove unused method
new b929cdb JAMES-3472 Add EmailChangesMethod integration test for distributed environment
The 11 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails. The revisions
listed as "add" were already present in the repository and have only
been added to this reference.
Summary of changes:
.../mailbox/cassandra/ids/CassandraMessageId.java | 2 +-
.../james/modules/data/CassandraJmapModule.java | 2 +
...Module.java => CassandraEmailChangeModule.java} | 22 +-
.../change/CassandraEmailChangeRepository.java | 56 +-
...itoryDAO.java => EmailChangeRepositoryDAO.java} | 58 +-
...geTable.java => CassandraEmailChangeTable.java} | 6 +-
...ava => CassandraEmailChangeRepositoryTest.java} | 33 +-
.../api/change/EmailChangeRepositoryContract.java | 699 +++++++++++++--------
.../change/MemoryEmailChangeRepositoryTest.java | 16 +-
....java => DistributedEmailChangeMethodTest.java} | 11 +-
.../distributed/DistributedEmailSetMethodTest.java | 13 +
.../contract/EmailChangesMethodContract.scala | 5 +-
.../rfc8621/contract/EmailSetMethodContract.scala | 555 ++++++++++++----
.../EmailSubmissionSetMethodContract.scala | 4 +
.../memory/MemoryEmailChangesMethodTest.java | 9 -
.../james/jmap/json/EmailSetSerializer.scala | 21 +-
.../org/apache/james/jmap/mail/EmailSet.scala | 1 +
.../apache/james/jmap/method/EmailSetMethod.scala | 21 +-
18 files changed, 1058 insertions(+), 476 deletions(-)
copy server/data/data-jmap-cassandra/src/main/java/org/apache/james/jmap/cassandra/change/{CassandraMailboxChangeModule.java => CassandraEmailChangeModule.java} (85%)
copy server/data/data-jmap-cassandra/src/main/java/org/apache/james/jmap/cassandra/change/{MailboxChangeRepositoryDAO.java => EmailChangeRepositoryDAO.java} (81%)
copy server/data/data-jmap-cassandra/src/main/java/org/apache/james/jmap/cassandra/change/tables/{CassandraMailboxChangeTable.java => CassandraEmailChangeTable.java} (91%)
copy server/data/data-jmap-cassandra/src/test/java/org/apache/james/jmap/cassandra/change/{CassandraMailboxChangeRepositoryTest.java => CassandraEmailChangeRepositoryTest.java} (66%)
copy server/protocols/jmap-rfc-8621-integration-tests/distributed-jmap-rfc-8621-integration-tests/src/test/java/org/apache/james/jmap/rfc8621/distributed/{DistributedMailboxChangeMethodTest.java => DistributedEmailChangeMethodTest.java} (88%)
---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscribe@james.apache.org
For additional commands, e-mail: notifications-help@james.apache.org
[james-project] 02/11: JAMES-3436 Email/set create should reject
headers properties
Posted by rc...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
rcordier pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/james-project.git
commit 5acfb985ef72403ca59cd53484172cac9227afea
Author: LanKhuat <dl...@linagora.com>
AuthorDate: Tue Jan 12 17:51:03 2021 +0700
JAMES-3436 Email/set create should reject headers properties
---
.../rfc8621/contract/EmailSetMethodContract.scala | 54 ++++++++++++++++++++++
.../james/jmap/json/EmailSetSerializer.scala | 21 +++++----
2 files changed, 67 insertions(+), 8 deletions(-)
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/EmailSetMethodContract.scala b/server/protocols/jmap-rfc-8621-integration-tests/jmap-rfc-8621-integration-tests-common/src/main/scala/org/apache/james/jmap/rfc8621/contract/EmailSetMethodContract.scala
index b39614d..a4cff0d 100644
--- a/server/protocols/jmap-rfc-8621-integration-tests/jmap-rfc-8621-integration-tests-common/src/main/scala/org/apache/james/jmap/rfc8621/contract/EmailSetMethodContract.scala
+++ b/server/protocols/jmap-rfc-8621-integration-tests/jmap-rfc-8621-integration-tests-common/src/main/scala/org/apache/james/jmap/rfc8621/contract/EmailSetMethodContract.scala
@@ -404,6 +404,60 @@ trait EmailSetMethodContract {
}
@Test
+ def createShouldFailWhenEmailContainsHeadersProperties(server: GuiceJamesServer): Unit = {
+ val bobPath = MailboxPath.inbox(BOB)
+ val mailboxId = server.getProbe(classOf[MailboxProbeImpl]).createMailbox(bobPath)
+
+ val request =
+ s"""{
+ | "using": ["urn:ietf:params:jmap:core", "urn:ietf:params:jmap:mail"],
+ | "methodCalls": [
+ | ["Email/set", {
+ | "accountId": "$ACCOUNT_ID",
+ | "create": {
+ | "aaaaaa":{
+ | "mailboxIds": {
+ | "${mailboxId.serialize}": true
+ | },
+ | "headers": [
+ | {
+ | "name": "Content-Type",
+ | "value": " text/plain; charset=utf-8; format=flowed"
+ | },
+ | {
+ | "name": "Content-Transfer-Encoding",
+ | "value": " 7bit"
+ | }
+ | ]
+ | }
+ | }
+ | }, "c1"]]
+ |}""".stripMargin
+
+ val response = `given`
+ .header(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER)
+ .body(request)
+ .when
+ .post
+ .`then`
+ .statusCode(SC_OK)
+ .contentType(JSON)
+ .extract
+ .body
+ .asString
+
+ assertThatJson(response)
+ .inPath("methodResponses[0][1].notCreated")
+ .isEqualTo(
+ s"""{
+ | "aaaaaa": {
+ | "type": "invalidArguments",
+ | "description": "List((,List(JsonValidationError(List('headers' is not allowed),ArraySeq()))))"
+ | }
+ |}""".stripMargin)
+ }
+
+ @Test
def shouldNotResetKeywordWhenFalseValue(server: GuiceJamesServer): Unit = {
val message: Message = Fixture.createTestMessage
diff --git a/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/json/EmailSetSerializer.scala b/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/json/EmailSetSerializer.scala
index 0ad72f6..83fa593 100644
--- a/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/json/EmailSetSerializer.scala
+++ b/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/json/EmailSetSerializer.scala
@@ -355,12 +355,15 @@ class EmailSetSerializer @Inject()(messageIdFactory: MessageId.Factory, mailboxI
private implicit val emailCreationRequestWithoutHeadersReads: Reads[EmailCreationRequestWithoutHeaders] = Json.reads[EmailCreationRequestWithoutHeaders]
private implicit val emailCreationRequestReads: Reads[EmailCreationRequest] = {
case o: JsObject =>
- val withoutHeader = emailCreationRequestWithoutHeadersReads.reads(o)
-
- val specificHeadersEither: Either[IllegalArgumentException, List[EmailHeader]] = o.value.toList
- .filter {
- case (name, _) => name.startsWith("header:")
- }.map {
+ if(o.value.contains("headers")) {
+ JsError("'headers' is not allowed")
+ } else {
+ val withoutHeader = emailCreationRequestWithoutHeadersReads.reads(o)
+
+ val specificHeadersEither: Either[IllegalArgumentException, List[EmailHeader]] = o.value.toList
+ .filter {
+ case (name, _) => name.startsWith("header:")
+ }.map {
case (name, value) =>
val refinedName: Either[String, NonEmptyString] = refineV[NonEmpty](name)
refinedName.left.map(e => new IllegalArgumentException(e))
@@ -372,8 +375,10 @@ class EmailSetSerializer @Inject()(messageIdFactory: MessageId.Factory, mailboxI
.map(headerValue => EmailHeader(EmailHeaderName(specificHeaderRequest.headerName), headerValue)))
}.sequence
- specificHeadersEither.fold(e => JsError(e.getMessage),
- specificHeaders => withoutHeader.map(_.toCreationRequest(specificHeaders)))
+ specificHeadersEither.fold(e => JsError(e.getMessage),
+ specificHeaders => withoutHeader.map(_.toCreationRequest(specificHeaders)))
+ }
+
case _ => JsError("Expecting a JsObject to represent a creation request")
}
---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscribe@james.apache.org
For additional commands, e-mail: notifications-help@james.apache.org
[james-project] 03/11: JAMES-3474 Email/set should handle state
property
Posted by rc...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
rcordier pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/james-project.git
commit ac22a265774b9962272d42f9a91548157b2557c3
Author: LanKhuat <dl...@linagora.com>
AuthorDate: Fri Jan 8 11:21:55 2021 +0700
JAMES-3474 Email/set should handle state property
---
.../rfc8621/contract/EmailSetMethodContract.scala | 246 ++++++++++++++++++++-
.../org/apache/james/jmap/mail/EmailSet.scala | 1 +
.../apache/james/jmap/method/EmailSetMethod.scala | 21 +-
3 files changed, 264 insertions(+), 4 deletions(-)
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/EmailSetMethodContract.scala b/server/protocols/jmap-rfc-8621-integration-tests/jmap-rfc-8621-integration-tests-common/src/main/scala/org/apache/james/jmap/rfc8621/contract/EmailSetMethodContract.scala
index a4cff0d..2277986 100644
--- a/server/protocols/jmap-rfc-8621-integration-tests/jmap-rfc-8621-integration-tests-common/src/main/scala/org/apache/james/jmap/rfc8621/contract/EmailSetMethodContract.scala
+++ b/server/protocols/jmap-rfc-8621-integration-tests/jmap-rfc-8621-integration-tests-common/src/main/scala/org/apache/james/jmap/rfc8621/contract/EmailSetMethodContract.scala
@@ -25,7 +25,7 @@ import java.time.format.DateTimeFormatter
import java.util.Date
import io.netty.handler.codec.http.HttpHeaderNames.ACCEPT
-import io.restassured.RestAssured.{`given`, requestSpecification}
+import io.restassured.RestAssured.{`given`, `with`, requestSpecification}
import io.restassured.builder.ResponseSpecBuilder
import io.restassured.http.ContentType.JSON
import javax.mail.Flags
@@ -48,6 +48,7 @@ import org.apache.james.mime4j.dom.Message
import org.apache.james.modules.{ACLProbeImpl, MailboxProbeImpl}
import org.apache.james.utils.DataProbeImpl
import org.assertj.core.api.Assertions.assertThat
+import org.hamcrest.Matchers.{equalTo, not}
import org.junit.jupiter.api.{BeforeEach, Test}
import org.junit.jupiter.params.ParameterizedTest
import org.junit.jupiter.params.provider.ValueSource
@@ -6289,6 +6290,249 @@ trait EmailSetMethodContract {
|}""".stripMargin)
}
+ @Test
+ def newStateShouldBeUpToDate(server: GuiceJamesServer): Unit = {
+ val mailboxProbe = server.getProbe(classOf[MailboxProbeImpl])
+ val mailboxId: MailboxId = mailboxProbe.createMailbox(MailboxPath.forUser(BOB, "mailbox"))
+
+ val request =
+ s"""
+ |{
+ | "using": [
+ | "urn:ietf:params:jmap:core",
+ | "urn:ietf:params:jmap:mail"],
+ | "methodCalls": [
+ | ["Email/set", {
+ | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6",
+ | "create": {
+ | "aaaaaa": {
+ | "mailboxIds": {
+ | "${mailboxId.serialize()}": true
+ | }
+ | }
+ | }
+ | }, "c1"],
+ | ["Email/changes", {
+ | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6",
+ | "#sinceState": {
+ | "resultOf":"c1",
+ | "name":"Email/set",
+ | "path":"newState"
+ | }
+ | }, "c2"]
+ | ]
+ |}
+ |""".stripMargin
+
+ val response = `given`
+ .header(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER)
+ .body(request)
+ .when
+ .post
+ .`then`
+ .log().ifValidationFails()
+ .statusCode(SC_OK)
+ .contentType(JSON)
+ .extract
+ .body
+ .asString
+
+ assertThatJson(response)
+ .withOptions(new Options(Option.IGNORING_ARRAY_ORDER))
+ .whenIgnoringPaths("methodResponses[1][1].oldState",
+ "methodResponses[1][1].newState")
+ .inPath("methodResponses[1][1]")
+ .isEqualTo(
+ s"""{
+ | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6",
+ | "hasMoreChanges": false,
+ | "created": [],
+ | "updated": [],
+ | "destroyed": []
+ |}""".stripMargin)
+ }
+
+ @Test
+ def oldStateShouldIncludeSetChanges(server: GuiceJamesServer): Unit = {
+ val path: MailboxPath = MailboxPath.forUser(BOB, "mailbox")
+ server.getProbe(classOf[MailboxProbeImpl]).createMailbox(path)
+
+ val message: Message = Fixture.createTestMessage
+ val messageId: MessageId = server.getProbe(classOf[MailboxProbeImpl])
+ .appendMessage(BOB.asString(), path,
+ AppendCommand.builder()
+ .build(message))
+ .getMessageId
+
+ val request =
+ s"""
+ |{
+ | "using": [
+ | "urn:ietf:params:jmap:core",
+ | "urn:ietf:params:jmap:mail"],
+ | "methodCalls": [
+ | ["Email/set", {
+ | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6",
+ | "update": {
+ | "${messageId.serialize}": {
+ | "keywords": {
+ | "music": true
+ | }
+ | }
+ | }
+ | }, "c1"],
+ | ["Email/changes", {
+ | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6",
+ | "#sinceState": {
+ | "resultOf":"c1",
+ | "name":"Email/set",
+ | "path":"oldState"
+ | }
+ | }, "c2"]
+ | ]
+ |}
+ |""".stripMargin
+
+ val response = `given`
+ .header(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER)
+ .body(request)
+ .when
+ .post
+ .`then`
+ .log().ifValidationFails()
+ .statusCode(SC_OK)
+ .contentType(JSON)
+ .extract
+ .body
+ .asString
+
+ assertThatJson(response)
+ .withOptions(new Options(Option.IGNORING_ARRAY_ORDER))
+ .whenIgnoringPaths("methodResponses[1][1].oldState", "methodResponses[1][1].newState")
+ .inPath("methodResponses[1][1]")
+ .isEqualTo(
+ s"""{
+ | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6",
+ | "hasMoreChanges": false,
+ | "created": [],
+ | "updated": ["${messageId.serialize}"],
+ | "destroyed": []
+ |}""".stripMargin)
+ }
+
+ @Test
+ def stateShouldNotTakeIntoAccountDelegationWhenNoCapability(server: GuiceJamesServer): Unit = {
+ val state: String = `with`()
+ .header(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER)
+ .body(
+ s"""{
+ | "using": [
+ | "urn:ietf:params:jmap:core",
+ | "urn:ietf:params:jmap:mail"],
+ | "methodCalls": [
+ | ["Email/get", {
+ | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6",
+ | "ids": []
+ | }, "c1"]
+ | ]
+ |}""".stripMargin)
+ .post
+ .`then`()
+ .extract()
+ .jsonPath()
+ .get("methodResponses[0][1].state")
+
+ val sharedMailboxName = "AndreShared"
+ val andreMailboxPath = MailboxPath.forUser(ANDRE, sharedMailboxName)
+ server.getProbe(classOf[MailboxProbeImpl])
+ .createMailbox(andreMailboxPath)
+
+ server.getProbe(classOf[ACLProbeImpl])
+ .replaceRights(andreMailboxPath, BOB.asString, new MailboxACL.Rfc4314Rights(Right.Lookup))
+
+ val message: Message = Fixture.createTestMessage
+ server.getProbe(classOf[MailboxProbeImpl])
+ .appendMessage(ANDRE.asString(), andreMailboxPath,
+ AppendCommand.builder()
+ .build(message))
+ .getMessageId
+
+ `given`
+ .header(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER)
+ .body(s"""{
+ | "using": [
+ | "urn:ietf:params:jmap:core",
+ | "urn:ietf:params:jmap:mail"],
+ | "methodCalls": [
+ | ["Email/set", {
+ | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6"
+ | }, "c1"]
+ | ]
+ |}""".stripMargin)
+ .when
+ .post
+ .`then`
+ .statusCode(SC_OK)
+ .body("methodResponses[0][1].oldState", equalTo(state))
+ }
+
+ @Test
+ def stateShouldTakeIntoAccountDelegationWhenCapability(server: GuiceJamesServer): Unit = {
+ val state: String = `with`()
+ .header(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER)
+ .body(
+ s"""{
+ | "using": [
+ | "urn:ietf:params:jmap:core",
+ | "urn:ietf:params:jmap:mail"],
+ | "methodCalls": [
+ | ["Email/get", {
+ | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6",
+ | "ids":[]
+ | }, "c1"]
+ | ]
+ |}""".stripMargin)
+ .post
+ .`then`()
+ .extract()
+ .jsonPath()
+ .get("methodResponses[0][1].state")
+
+ val sharedMailboxName = "AndreShared"
+ val andreMailboxPath = MailboxPath.forUser(ANDRE, sharedMailboxName)
+ server.getProbe(classOf[MailboxProbeImpl])
+ .createMailbox(andreMailboxPath)
+
+ server.getProbe(classOf[ACLProbeImpl])
+ .replaceRights(andreMailboxPath, BOB.asString, new MailboxACL.Rfc4314Rights(Right.Lookup))
+
+ val message: Message = Fixture.createTestMessage
+ server.getProbe(classOf[MailboxProbeImpl])
+ .appendMessage(ANDRE.asString(), andreMailboxPath,
+ AppendCommand.builder()
+ .build(message))
+ .getMessageId
+
+ `given`
+ .header(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER)
+ .body(s"""{
+ | "using": [
+ | "urn:ietf:params:jmap:core",
+ | "urn:ietf:params:jmap:mail",
+ | "urn:apache:james:params:jmap:mail:shares"],
+ | "methodCalls": [
+ | ["Email/set", {
+ | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6"
+ | }, "c1"]
+ | ]
+ |}""".stripMargin)
+ .when
+ .post
+ .`then`
+ .statusCode(SC_OK)
+ .body("methodResponses[0][1].oldState", not(equalTo(state)))
+ }
+
private def buildTestMessage = {
Message.Builder
.of
diff --git a/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/mail/EmailSet.scala b/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/mail/EmailSet.scala
index f56f5ba..a9fb1e9 100644
--- a/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/mail/EmailSet.scala
+++ b/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/mail/EmailSet.scala
@@ -338,6 +338,7 @@ case class EmailSetRequest(accountId: AccountId,
destroy: Option[DestroyIds]) extends WithAccountId
case class EmailSetResponse(accountId: AccountId,
+ oldState: Option[State],
newState: State,
created: Option[Map[EmailCreationId, EmailCreationResponse]],
notCreated: Option[Map[EmailCreationId, SetError]],
diff --git a/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/EmailSetMethod.scala b/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/EmailSetMethod.scala
index 4a69b2c..bd52c8b 100644
--- a/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/EmailSetMethod.scala
+++ b/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/EmailSetMethod.scala
@@ -20,7 +20,9 @@ package org.apache.james.jmap.method
import eu.timepit.refined.auto._
import javax.inject.Inject
-import org.apache.james.jmap.core.CapabilityIdentifier.{CapabilityIdentifier, JMAP_CORE, JMAP_MAIL}
+import org.apache.james.jmap.api.change.EmailChangeRepository
+import org.apache.james.jmap.api.model.{AccountId => JavaAccountId}
+import org.apache.james.jmap.core.CapabilityIdentifier.{CapabilityIdentifier, JAMES_SHARES, JMAP_CORE, JMAP_MAIL}
import org.apache.james.jmap.core.Invocation.{Arguments, MethodName}
import org.apache.james.jmap.core.{ClientId, Id, Invocation, ServerId, State}
import org.apache.james.jmap.json.{EmailSetSerializer, ResponseSerializer}
@@ -39,21 +41,25 @@ class EmailSetMethod @Inject()(serializer: EmailSetSerializer,
val sessionSupplier: SessionSupplier,
createPerformer: EmailSetCreatePerformer,
deletePerformer: EmailSetDeletePerformer,
- updatePerformer: EmailSetUpdatePerformer) extends MethodRequiringAccountId[EmailSetRequest] {
+ updatePerformer: EmailSetUpdatePerformer,
+ emailChangeRepository: EmailChangeRepository) extends MethodRequiringAccountId[EmailSetRequest] {
override val methodName: MethodName = MethodName("Email/set")
override val requiredCapabilities: Set[CapabilityIdentifier] = Set(JMAP_CORE, JMAP_MAIL)
override def doProcess(capabilities: Set[CapabilityIdentifier], invocation: InvocationWithContext, mailboxSession: MailboxSession, request: EmailSetRequest): SMono[InvocationWithContext] = {
for {
+ oldState <- retrieveState(capabilities, mailboxSession)
destroyResults <- deletePerformer.destroy(request, mailboxSession)
updateResults <- updatePerformer.update(request, mailboxSession)
created <- createPerformer.create(request, mailboxSession)
+ newState <- retrieveState(capabilities, mailboxSession)
} yield InvocationWithContext(
invocation = Invocation(
methodName = methodName,
arguments = Arguments(serializer.serialize(EmailSetResponse(
accountId = request.accountId,
- newState = State.INSTANCE,
+ oldState = Some(oldState),
+ newState = newState,
created = created.created,
notCreated = created.notCreated,
updated = updateResults.updated,
@@ -75,4 +81,13 @@ class EmailSetMethod @Inject()(serializer: EmailSetSerializer,
case JsSuccess(emailSetRequest, _) => Right(emailSetRequest)
case errors: JsError => Left(new IllegalArgumentException(ResponseSerializer.serialize(errors).toString))
}
+
+ private def retrieveState(capabilities: Set[CapabilityIdentifier], mailboxSession: MailboxSession): SMono[State] =
+ if (capabilities.contains(JAMES_SHARES)) {
+ SMono(emailChangeRepository.getLatestStateWithDelegation(JavaAccountId.fromUsername(mailboxSession.getUser)))
+ .map(State.fromJava)
+ } else {
+ SMono(emailChangeRepository.getLatestState(JavaAccountId.fromUsername(mailboxSession.getUser)))
+ .map(State.fromJava)
+ }
}
\ No newline at end of file
---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscribe@james.apache.org
For additional commands, e-mail: notifications-help@james.apache.org
[james-project] 06/11: JAMES-3470 CassandraEmailChangeRepository
implementation
Posted by rc...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
rcordier pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/james-project.git
commit 0c6015b92358d0844750652b5dd5c8f049c26698
Author: LanKhuat <dl...@linagora.com>
AuthorDate: Mon Jan 11 10:10:15 2021 +0700
JAMES-3470 CassandraEmailChangeRepository implementation
---
.../change/CassandraEmailChangeModule.java | 58 +++++++
.../change/CassandraEmailChangeRepository.java | 56 ++++++-
.../cassandra/change/EmailChangeRepositoryDAO.java | 172 +++++++++++++++++++++
.../change/tables/CassandraEmailChangeTable.java | 31 ++++
.../change/CassandraEmailChangeRepositoryTest.java | 53 +++++++
5 files changed, 363 insertions(+), 7 deletions(-)
diff --git a/server/data/data-jmap-cassandra/src/main/java/org/apache/james/jmap/cassandra/change/CassandraEmailChangeModule.java b/server/data/data-jmap-cassandra/src/main/java/org/apache/james/jmap/cassandra/change/CassandraEmailChangeModule.java
new file mode 100644
index 0000000..abe9f3d
--- /dev/null
+++ b/server/data/data-jmap-cassandra/src/main/java/org/apache/james/jmap/cassandra/change/CassandraEmailChangeModule.java
@@ -0,0 +1,58 @@
+/****************************************************************
+ * 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.cassandra.change;
+
+import static com.datastax.driver.core.DataType.cboolean;
+import static com.datastax.driver.core.DataType.frozenSet;
+import static com.datastax.driver.core.DataType.text;
+import static com.datastax.driver.core.DataType.timeuuid;
+import static com.datastax.driver.core.schemabuilder.SchemaBuilder.Direction.ASC;
+import static com.datastax.driver.core.schemabuilder.SchemaBuilder.KeyCaching.ALL;
+import static com.datastax.driver.core.schemabuilder.SchemaBuilder.frozen;
+import static com.datastax.driver.core.schemabuilder.SchemaBuilder.rows;
+import static org.apache.james.backends.cassandra.init.CassandraZonedDateTimeModule.ZONED_DATE_TIME;
+import static org.apache.james.backends.cassandra.utils.CassandraConstants.DEFAULT_CACHED_ROW_PER_PARTITION;
+import static org.apache.james.jmap.cassandra.change.tables.CassandraEmailChangeTable.ACCOUNT_ID;
+import static org.apache.james.jmap.cassandra.change.tables.CassandraEmailChangeTable.CREATED;
+import static org.apache.james.jmap.cassandra.change.tables.CassandraEmailChangeTable.DATE;
+import static org.apache.james.jmap.cassandra.change.tables.CassandraEmailChangeTable.DESTROYED;
+import static org.apache.james.jmap.cassandra.change.tables.CassandraEmailChangeTable.IS_DELEGATED;
+import static org.apache.james.jmap.cassandra.change.tables.CassandraEmailChangeTable.STATE;
+import static org.apache.james.jmap.cassandra.change.tables.CassandraEmailChangeTable.TABLE_NAME;
+import static org.apache.james.jmap.cassandra.change.tables.CassandraEmailChangeTable.UPDATED;
+
+import org.apache.james.backends.cassandra.components.CassandraModule;
+
+public interface CassandraEmailChangeModule {
+ CassandraModule MODULE = CassandraModule.table(TABLE_NAME)
+ .comment("Holds EmailChange definition. Used to manage Email state in JMAP.")
+ .options(options -> options
+ .clusteringOrder(STATE, ASC)
+ .caching(ALL, rows(DEFAULT_CACHED_ROW_PER_PARTITION)))
+ .statement(statement -> statement
+ .addPartitionKey(ACCOUNT_ID, text())
+ .addClusteringColumn(STATE, timeuuid())
+ .addUDTColumn(DATE, frozen(ZONED_DATE_TIME))
+ .addColumn(IS_DELEGATED, cboolean())
+ .addColumn(CREATED, frozenSet(timeuuid()))
+ .addColumn(UPDATED, frozenSet(timeuuid()))
+ .addColumn(DESTROYED, frozenSet(timeuuid())))
+ .build();
+}
diff --git a/server/data/data-jmap-cassandra/src/main/java/org/apache/james/jmap/cassandra/change/CassandraEmailChangeRepository.java b/server/data/data-jmap-cassandra/src/main/java/org/apache/james/jmap/cassandra/change/CassandraEmailChangeRepository.java
index 1f67589..59b1f77 100644
--- a/server/data/data-jmap-cassandra/src/main/java/org/apache/james/jmap/cassandra/change/CassandraEmailChangeRepository.java
+++ b/server/data/data-jmap-cassandra/src/main/java/org/apache/james/jmap/cassandra/change/CassandraEmailChangeRepository.java
@@ -21,39 +21,81 @@ package org.apache.james.jmap.cassandra.change;
import java.util.Optional;
+import javax.inject.Inject;
+
import org.apache.james.jmap.api.change.EmailChange;
import org.apache.james.jmap.api.change.EmailChangeRepository;
import org.apache.james.jmap.api.change.EmailChanges;
import org.apache.james.jmap.api.change.Limit;
import org.apache.james.jmap.api.change.State;
+import org.apache.james.jmap.api.exception.ChangeNotFoundException;
import org.apache.james.jmap.api.model.AccountId;
+import com.google.common.base.Preconditions;
+
+import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
public class CassandraEmailChangeRepository implements EmailChangeRepository {
+ public static final Limit DEFAULT_NUMBER_OF_CHANGES = Limit.of(5);
+
+ private final EmailChangeRepositoryDAO emailChangeRepositoryDAO;
+
+ @Inject
+ public CassandraEmailChangeRepository(EmailChangeRepositoryDAO emailChangeRepositoryDAO) {
+ this.emailChangeRepositoryDAO = emailChangeRepositoryDAO;
+ }
@Override
public Mono<Void> save(EmailChange change) {
- return Mono.empty();
+ return emailChangeRepositoryDAO.insert(change);
}
@Override
- public Mono<EmailChanges> getSinceState(AccountId accountId, State state, Optional<Limit> maxIdsToReturn) {
- return Mono.empty();
+ public Mono<EmailChanges> getSinceState(AccountId accountId, State state, Optional<Limit> maxChanges) {
+ Preconditions.checkNotNull(accountId);
+ Preconditions.checkNotNull(state);
+ maxChanges.ifPresent(limit -> Preconditions.checkArgument(limit.getValue() > 0, "maxChanges must be a positive integer"));
+
+ if (state.equals(State.INITIAL)) {
+ return emailChangeRepositoryDAO.getAllChanges(accountId)
+ .filter(change -> !change.isDelegated())
+ .collect(new EmailChanges.Builder.EmailChangeCollector(state, maxChanges.orElse(DEFAULT_NUMBER_OF_CHANGES)));
+ }
+
+ return emailChangeRepositoryDAO.getChangesSince(accountId, state)
+ .switchIfEmpty(Flux.error(new ChangeNotFoundException(state, String.format("State '%s' could not be found", state.getValue()))))
+ .filter(change -> !change.isDelegated())
+ .filter(change -> !change.getState().equals(state))
+ .collect(new EmailChanges.Builder.EmailChangeCollector(state, maxChanges.orElse(DEFAULT_NUMBER_OF_CHANGES)));
}
@Override
- public Mono<EmailChanges> getSinceStateWithDelegation(AccountId accountId, State state, Optional<Limit> maxIdsToReturn) {
- return Mono.empty();
+ public Mono<EmailChanges> getSinceStateWithDelegation(AccountId accountId, State state, Optional<Limit> maxChanges) {
+ Preconditions.checkNotNull(accountId);
+ Preconditions.checkNotNull(state);
+ maxChanges.ifPresent(limit -> Preconditions.checkArgument(limit.getValue() > 0, "maxChanges must be a positive integer"));
+
+ if (state.equals(State.INITIAL)) {
+ return emailChangeRepositoryDAO.getAllChanges(accountId)
+ .collect(new EmailChanges.Builder.EmailChangeCollector(state, maxChanges.orElse(DEFAULT_NUMBER_OF_CHANGES)));
+ }
+
+ return emailChangeRepositoryDAO.getChangesSince(accountId, state)
+ .switchIfEmpty(Flux.error(new ChangeNotFoundException(state, String.format("State '%s' could not be found", state.getValue()))))
+ .filter(change -> !change.getState().equals(state))
+ .collect(new EmailChanges.Builder.EmailChangeCollector(state, maxChanges.orElse(DEFAULT_NUMBER_OF_CHANGES)));
}
@Override
public Mono<State> getLatestState(AccountId accountId) {
- return Mono.just(State.INITIAL);
+ return emailChangeRepositoryDAO.latestStateNotDelegated(accountId)
+ .switchIfEmpty(Mono.just(State.INITIAL));
}
@Override
public Mono<State> getLatestStateWithDelegation(AccountId accountId) {
- return Mono.just(State.INITIAL);
+ return emailChangeRepositoryDAO.latestState(accountId)
+ .switchIfEmpty(Mono.just(State.INITIAL));
}
}
diff --git a/server/data/data-jmap-cassandra/src/main/java/org/apache/james/jmap/cassandra/change/EmailChangeRepositoryDAO.java b/server/data/data-jmap-cassandra/src/main/java/org/apache/james/jmap/cassandra/change/EmailChangeRepositoryDAO.java
new file mode 100644
index 0000000..4799908
--- /dev/null
+++ b/server/data/data-jmap-cassandra/src/main/java/org/apache/james/jmap/cassandra/change/EmailChangeRepositoryDAO.java
@@ -0,0 +1,172 @@
+/****************************************************************
+ * 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.cassandra.change;
+
+import static com.datastax.driver.core.querybuilder.QueryBuilder.asc;
+import static com.datastax.driver.core.querybuilder.QueryBuilder.bindMarker;
+import static com.datastax.driver.core.querybuilder.QueryBuilder.desc;
+import static com.datastax.driver.core.querybuilder.QueryBuilder.eq;
+import static com.datastax.driver.core.querybuilder.QueryBuilder.gte;
+import static com.datastax.driver.core.querybuilder.QueryBuilder.insertInto;
+import static com.datastax.driver.core.querybuilder.QueryBuilder.select;
+import static org.apache.james.jmap.cassandra.change.tables.CassandraEmailChangeTable.ACCOUNT_ID;
+import static org.apache.james.jmap.cassandra.change.tables.CassandraEmailChangeTable.CREATED;
+import static org.apache.james.jmap.cassandra.change.tables.CassandraEmailChangeTable.DATE;
+import static org.apache.james.jmap.cassandra.change.tables.CassandraEmailChangeTable.DESTROYED;
+import static org.apache.james.jmap.cassandra.change.tables.CassandraEmailChangeTable.IS_DELEGATED;
+import static org.apache.james.jmap.cassandra.change.tables.CassandraEmailChangeTable.STATE;
+import static org.apache.james.jmap.cassandra.change.tables.CassandraEmailChangeTable.TABLE_NAME;
+import static org.apache.james.jmap.cassandra.change.tables.CassandraEmailChangeTable.UPDATED;
+
+import java.util.List;
+import java.util.Set;
+import java.util.UUID;
+
+import javax.inject.Inject;
+
+import org.apache.james.backends.cassandra.init.CassandraTypesProvider;
+import org.apache.james.backends.cassandra.init.CassandraZonedDateTimeModule;
+import org.apache.james.backends.cassandra.utils.CassandraAsyncExecutor;
+import org.apache.james.jmap.api.change.EmailChange;
+import org.apache.james.jmap.api.change.State;
+import org.apache.james.jmap.api.model.AccountId;
+import org.apache.james.mailbox.cassandra.ids.CassandraMessageId;
+import org.apache.james.mailbox.model.MessageId;
+
+import com.datastax.driver.core.PreparedStatement;
+import com.datastax.driver.core.Row;
+import com.datastax.driver.core.Session;
+import com.datastax.driver.core.UserType;
+import com.github.steveash.guavate.Guavate;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableSet;
+
+import reactor.core.publisher.Flux;
+import reactor.core.publisher.Mono;
+
+public class EmailChangeRepositoryDAO {
+ private final CassandraAsyncExecutor executor;
+ private final UserType zonedDateTimeUserType;
+ private final PreparedStatement insertStatement;
+ private final PreparedStatement selectAllStatement;
+ private final PreparedStatement selectFromStatement;
+ private final PreparedStatement selectLatestStatement;
+ private final PreparedStatement selectLatestNotDelegatedStatement;
+
+ @Inject
+ public EmailChangeRepositoryDAO(Session session, CassandraTypesProvider cassandraTypesProvider) {
+ executor = new CassandraAsyncExecutor(session);
+ zonedDateTimeUserType = cassandraTypesProvider.getDefinedUserType(CassandraZonedDateTimeModule.ZONED_DATE_TIME);
+
+ insertStatement = session.prepare(insertInto(TABLE_NAME)
+ .value(ACCOUNT_ID, bindMarker(ACCOUNT_ID))
+ .value(STATE, bindMarker(STATE))
+ .value(DATE, bindMarker(DATE))
+ .value(IS_DELEGATED, bindMarker(IS_DELEGATED))
+ .value(CREATED, bindMarker(CREATED))
+ .value(UPDATED, bindMarker(UPDATED))
+ .value(DESTROYED, bindMarker(DESTROYED)));
+
+ selectAllStatement = session.prepare(select().from(TABLE_NAME)
+ .where(eq(ACCOUNT_ID, bindMarker(ACCOUNT_ID)))
+ .orderBy(asc(STATE)));
+
+ selectFromStatement = session.prepare(select().from(TABLE_NAME)
+ .where(eq(ACCOUNT_ID, bindMarker(ACCOUNT_ID)))
+ .and(gte(STATE, bindMarker(STATE)))
+ .orderBy(asc(STATE)));
+
+ selectLatestStatement = session.prepare(select(STATE)
+ .from(TABLE_NAME)
+ .where(eq(ACCOUNT_ID, bindMarker(ACCOUNT_ID)))
+ .orderBy(desc(STATE))
+ .limit(1));
+
+ selectLatestNotDelegatedStatement = session.prepare(select(STATE)
+ .from(TABLE_NAME)
+ .where(eq(ACCOUNT_ID, bindMarker(ACCOUNT_ID)))
+ .and(eq(IS_DELEGATED, false))
+ .orderBy(desc(STATE))
+ .limit(1)
+ .allowFiltering());
+ }
+
+ Mono<Void> insert(EmailChange change) {
+ return executor.executeVoid(insertStatement.bind()
+ .setString(ACCOUNT_ID, change.getAccountId().getIdentifier())
+ .setUUID(STATE, change.getState().getValue())
+ .setBool(IS_DELEGATED, change.isDelegated())
+ .setSet(CREATED, toUuidSet(change.getCreated()), UUID.class)
+ .setSet(UPDATED, toUuidSet(change.getUpdated()), UUID.class)
+ .setSet(DESTROYED, toUuidSet(change.getDestroyed()), UUID.class)
+ .setUDTValue(DATE, CassandraZonedDateTimeModule.toUDT(zonedDateTimeUserType, change.getDate())));
+ }
+
+ private ImmutableSet<UUID> toUuidSet(List<MessageId> idSet) {
+ return idSet.stream()
+ .filter(CassandraMessageId.class::isInstance)
+ .map(CassandraMessageId.class::cast)
+ .map(CassandraMessageId::get)
+ .collect(Guavate.toImmutableSet());
+ }
+
+ Flux<EmailChange> getAllChanges(AccountId accountId) {
+ return executor.executeRows(selectAllStatement.bind()
+ .setString(ACCOUNT_ID, accountId.getIdentifier()))
+ .map(this::readRow);
+ }
+
+ Flux<EmailChange> getChangesSince(AccountId accountId, State state) {
+ return executor.executeRows(selectFromStatement.bind()
+ .setString(ACCOUNT_ID, accountId.getIdentifier())
+ .setUUID(STATE, state.getValue()))
+ .map(this::readRow);
+ }
+
+ Mono<State> latestState(AccountId accountId) {
+ return executor.executeSingleRow(selectLatestStatement.bind()
+ .setString(ACCOUNT_ID, accountId.getIdentifier()))
+ .map(row -> State.of(row.getUUID(STATE)));
+ }
+
+ Mono<State> latestStateNotDelegated(AccountId accountId) {
+ return executor.executeSingleRow(selectLatestNotDelegatedStatement.bind()
+ .setString(ACCOUNT_ID, accountId.getIdentifier()))
+ .map(row -> State.of(row.getUUID(STATE)));
+ }
+
+ private EmailChange readRow(Row row) {
+ return EmailChange.builder()
+ .accountId(AccountId.fromString(row.getString(ACCOUNT_ID)))
+ .state(State.of(row.getUUID(STATE)))
+ .date(CassandraZonedDateTimeModule.fromUDT(row.getUDTValue(DATE)))
+ .isDelegated(row.getBool(IS_DELEGATED))
+ .created(toIdSet(row.getSet(CREATED, UUID.class)))
+ .updated(toIdSet(row.getSet(UPDATED, UUID.class)))
+ .destroyed(toIdSet(row.getSet(DESTROYED, UUID.class)))
+ .build();
+ }
+
+ private ImmutableList<MessageId> toIdSet(Set<UUID> uuidSet) {
+ return uuidSet.stream()
+ .map(CassandraMessageId.Factory::of)
+ .collect(Guavate.toImmutableList());
+ }
+}
diff --git a/server/data/data-jmap-cassandra/src/main/java/org/apache/james/jmap/cassandra/change/tables/CassandraEmailChangeTable.java b/server/data/data-jmap-cassandra/src/main/java/org/apache/james/jmap/cassandra/change/tables/CassandraEmailChangeTable.java
new file mode 100644
index 0000000..945f038
--- /dev/null
+++ b/server/data/data-jmap-cassandra/src/main/java/org/apache/james/jmap/cassandra/change/tables/CassandraEmailChangeTable.java
@@ -0,0 +1,31 @@
+/****************************************************************
+ * 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.cassandra.change.tables;
+
+public interface CassandraEmailChangeTable {
+ String TABLE_NAME = "email_change";
+ String ACCOUNT_ID = "account_id";
+ String STATE = "state";
+ String DATE = "date";
+ String IS_DELEGATED = "is_delegated";
+ String CREATED = "created";
+ String UPDATED = "updated";
+ String DESTROYED = "destroyed";
+}
diff --git a/server/data/data-jmap-cassandra/src/test/java/org/apache/james/jmap/cassandra/change/CassandraEmailChangeRepositoryTest.java b/server/data/data-jmap-cassandra/src/test/java/org/apache/james/jmap/cassandra/change/CassandraEmailChangeRepositoryTest.java
new file mode 100644
index 0000000..50af3ff
--- /dev/null
+++ b/server/data/data-jmap-cassandra/src/test/java/org/apache/james/jmap/cassandra/change/CassandraEmailChangeRepositoryTest.java
@@ -0,0 +1,53 @@
+/****************************************************************
+ * 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.cassandra.change;
+
+import org.apache.james.backends.cassandra.CassandraCluster;
+import org.apache.james.backends.cassandra.CassandraClusterExtension;
+import org.apache.james.backends.cassandra.components.CassandraModule;
+import org.apache.james.backends.cassandra.init.CassandraZonedDateTimeModule;
+import org.apache.james.backends.cassandra.versions.CassandraSchemaVersionModule;
+import org.apache.james.jmap.api.change.EmailChangeRepository;
+import org.apache.james.jmap.api.change.EmailChangeRepositoryContract;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.extension.RegisterExtension;
+
+public class CassandraEmailChangeRepositoryTest implements EmailChangeRepositoryContract {
+
+ @RegisterExtension
+ static CassandraClusterExtension cassandraCluster = new CassandraClusterExtension(
+ CassandraModule.aggregateModules(CassandraEmailChangeModule.MODULE,
+ CassandraSchemaVersionModule.MODULE,
+ CassandraZonedDateTimeModule.MODULE));
+
+ EmailChangeRepository emailChangeRepository;
+ EmailChangeRepositoryDAO emailChangeRepositoryDAO;
+
+ @BeforeEach
+ public void setUp(CassandraCluster cassandra) {
+ emailChangeRepositoryDAO = new EmailChangeRepositoryDAO(cassandra.getConf(), cassandra.getTypesProvider());
+ emailChangeRepository = new CassandraEmailChangeRepository(emailChangeRepositoryDAO);
+ }
+
+ @Override
+ public EmailChangeRepository emailChangeRepository() {
+ return emailChangeRepository;
+ }
+}
---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscribe@james.apache.org
For additional commands, e-mail: notifications-help@james.apache.org
[james-project] 04/11: JAMES-3474 New/old state should be ignored
in irrelevant Email/set calls
Posted by rc...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
rcordier pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/james-project.git
commit 716b3037bc1e69aa39bd2fe66a4856cf72e3671f
Author: LanKhuat <dl...@linagora.com>
AuthorDate: Fri Jan 8 11:22:40 2021 +0700
JAMES-3474 New/old state should be ignored in irrelevant Email/set calls
---
.../rfc8621/contract/EmailSetMethodContract.scala | 239 ++++++++++++---------
.../EmailSubmissionSetMethodContract.scala | 4 +
2 files changed, 140 insertions(+), 103 deletions(-)
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/EmailSetMethodContract.scala b/server/protocols/jmap-rfc-8621-integration-tests/jmap-rfc-8621-integration-tests-common/src/main/scala/org/apache/james/jmap/rfc8621/contract/EmailSetMethodContract.scala
index 2277986..55f1b10 100644
--- a/server/protocols/jmap-rfc-8621-integration-tests/jmap-rfc-8621-integration-tests-common/src/main/scala/org/apache/james/jmap/rfc8621/contract/EmailSetMethodContract.scala
+++ b/server/protocols/jmap-rfc-8621-integration-tests/jmap-rfc-8621-integration-tests-common/src/main/scala/org/apache/james/jmap/rfc8621/contract/EmailSetMethodContract.scala
@@ -30,8 +30,11 @@ import io.restassured.builder.ResponseSpecBuilder
import io.restassured.http.ContentType.JSON
import javax.mail.Flags
import net.javacrumbs.jsonunit.assertj.JsonAssertions.assertThatJson
+import net.javacrumbs.jsonunit.core.Option
+import net.javacrumbs.jsonunit.core.internal.Options
import org.apache.http.HttpStatus.{SC_CREATED, SC_OK}
import org.apache.james.GuiceJamesServer
+import org.apache.james.jmap.api.change.State
import org.apache.james.jmap.core.ResponseObject.SESSION_STATE
import org.apache.james.jmap.core.State.INSTANCE
import org.apache.james.jmap.core.UTCDate
@@ -3076,7 +3079,9 @@ trait EmailSetMethodContract {
|}""".stripMargin)
assertThatJson(response)
- .whenIgnoringPaths("methodResponses[1][1].state")
+ .whenIgnoringPaths("methodResponses[0][1].oldState",
+ "methodResponses[0][1].newState",
+ "methodResponses[1][1].state")
.isEqualTo(
s"""{
| "sessionState": "${SESSION_STATE.value}",
@@ -3188,14 +3193,15 @@ trait EmailSetMethodContract {
.get.asInstanceOf[JsNumber].value
assertThatJson(response)
- .whenIgnoringPaths("methodResponses[1][1].state")
+ .whenIgnoringPaths("methodResponses[0][1].newState",
+ "methodResponses[1][1].state")
.isEqualTo(
s"""{
| "sessionState": "${SESSION_STATE.value}",
| "methodResponses": [
| ["Email/set", {
| "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6",
- | "newState": "${INSTANCE.value}",
+ | "oldState": "${State.INITIAL.getValue}",
| "created": {
| "aaaaaa": {
| "id": "$messageId",
@@ -4703,14 +4709,15 @@ trait EmailSetMethodContract {
.asString
assertThatJson(response)
- .whenIgnoringPaths("methodResponses[1][1].state")
+ .whenIgnoringPaths("methodResponses[0][1].oldState",
+ "methodResponses[0][1].newState",
+ "methodResponses[1][1].state")
.isEqualTo(
s"""{
| "sessionState": "${SESSION_STATE.value}",
| "methodResponses": [
| ["Email/set", {
| "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6",
- | "newState": "${INSTANCE.value}",
| "destroyed": ["${messageId.serialize}"]
| }, "c1"],
| ["Email/get", {
@@ -4749,21 +4756,23 @@ trait EmailSetMethodContract {
.body
.asString
- assertThatJson(response).isEqualTo(
- s"""{
- | "sessionState": "${SESSION_STATE.value}",
- | "methodResponses": [
- | ["Email/set", {
- | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6",
- | "newState": "${INSTANCE.value}",
- | "notDestroyed": {
- | "invalid": {
- | "type": "invalidArguments",
- | "description": "invalid is not a messageId: ${invalidMessageIdMessage("invalid")}"
- | }
- | }
- | }, "c1"]]
- |}""".stripMargin)
+ assertThatJson(response)
+ .whenIgnoringPaths("methodResponses[0][1].oldState",
+ "methodResponses[0][1].newState")
+ .isEqualTo(
+ s"""{
+ | "sessionState": "${SESSION_STATE.value}",
+ | "methodResponses": [
+ | ["Email/set", {
+ | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6",
+ | "notDestroyed": {
+ | "invalid": {
+ | "type": "invalidArguments",
+ | "description": "invalid is not a messageId: ${invalidMessageIdMessage("invalid")}"
+ | }
+ | }
+ | }, "c1"]]
+ |}""".stripMargin)
}
@Test
@@ -4794,21 +4803,23 @@ trait EmailSetMethodContract {
.body
.asString
- assertThatJson(response).isEqualTo(
- s"""{
- | "sessionState": "${SESSION_STATE.value}",
- | "methodResponses": [
- | ["Email/set", {
- | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6",
- | "newState": "${INSTANCE.value}",
- | "notDestroyed": {
- | "${messageId.serialize}": {
- | "type": "notFound",
- | "description": "Cannot find message with messageId: ${messageId.serialize}"
- | }
- | }
- | }, "c1"]]
- |}""".stripMargin)
+ assertThatJson(response)
+ .whenIgnoringPaths("methodResponses[0][1].oldState",
+ "methodResponses[0][1].newState")
+ .isEqualTo(
+ s"""{
+ | "sessionState": "${SESSION_STATE.value}",
+ | "methodResponses": [
+ | ["Email/set", {
+ | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6",
+ | "notDestroyed": {
+ | "${messageId.serialize}": {
+ | "type": "notFound",
+ | "description": "Cannot find message with messageId: ${messageId.serialize}"
+ | }
+ | }
+ | }, "c1"]]
+ |}""".stripMargin)
}
@Test
@@ -4846,22 +4857,24 @@ trait EmailSetMethodContract {
.body
.asString
- assertThatJson(response).isEqualTo(
- s"""{
- | "sessionState": "${SESSION_STATE.value}",
- | "methodResponses": [
- | ["Email/set", {
- | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6",
- | "newState": "${INSTANCE.value}",
- | "notDestroyed": {
- | "${messageId.serialize}": {
- | "type": "notFound",
- | "description": "Cannot find message with messageId: ${messageId.serialize}"
- | }
- | }
- | }, "c1"]
- | ]
- |}""".stripMargin)
+ assertThatJson(response)
+ .whenIgnoringPaths("methodResponses[0][1].oldState",
+ "methodResponses[0][1].newState")
+ .isEqualTo(
+ s"""{
+ | "sessionState": "${SESSION_STATE.value}",
+ | "methodResponses": [
+ | ["Email/set", {
+ | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6",
+ | "notDestroyed": {
+ | "${messageId.serialize}": {
+ | "type": "notFound",
+ | "description": "Cannot find message with messageId: ${messageId.serialize}"
+ | }
+ | }
+ | }, "c1"]
+ | ]
+ |}""".stripMargin)
}
@Test
@@ -4905,22 +4918,24 @@ trait EmailSetMethodContract {
.body
.asString
- assertThatJson(response).isEqualTo(
- s"""{
- | "sessionState": "${SESSION_STATE.value}",
- | "methodResponses": [
- | ["Email/set", {
- | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6",
- | "newState": "${INSTANCE.value}",
- | "notDestroyed": {
- | "${messageId.serialize}": {
- | "type": "notFound",
- | "description": "Cannot find message with messageId: ${messageId.serialize}"
- | }
- | }
- | }, "c1"]
- | ]
- |}""".stripMargin)
+ assertThatJson(response)
+ .whenIgnoringPaths("methodResponses[0][1].oldState",
+ "methodResponses[0][1].newState")
+ .isEqualTo(
+ s"""{
+ | "sessionState": "${SESSION_STATE.value}",
+ | "methodResponses": [
+ | ["Email/set", {
+ | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6",
+ | "notDestroyed": {
+ | "${messageId.serialize}": {
+ | "type": "notFound",
+ | "description": "Cannot find message with messageId: ${messageId.serialize}"
+ | }
+ | }
+ | }, "c1"]
+ | ]
+ |}""".stripMargin)
}
@Test
@@ -4970,14 +4985,15 @@ trait EmailSetMethodContract {
.asString
assertThatJson(response)
- .whenIgnoringPaths("methodResponses[1][1].state")
+ .whenIgnoringPaths("methodResponses[0][1].oldState",
+ "methodResponses[0][1].newState",
+ "methodResponses[1][1].state")
.isEqualTo(
s"""{
| "sessionState": "${SESSION_STATE.value}",
| "methodResponses": [
| ["Email/set", {
| "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6",
- | "newState": "${INSTANCE.value}",
| "destroyed": ["${messageId.serialize}"]
| }, "c1"],
| ["Email/get", {
@@ -5041,14 +5057,15 @@ trait EmailSetMethodContract {
.asString
assertThatJson(response)
- .whenIgnoringPaths("methodResponses[1][1].state")
+ .whenIgnoringPaths("methodResponses[0][1].oldState",
+ "methodResponses[0][1].newState",
+ "methodResponses[1][1].state")
.isEqualTo(
s"""{
| "sessionState": "${SESSION_STATE.value}",
| "methodResponses": [
| ["Email/set", {
| "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6",
- | "newState": "${INSTANCE.value}",
| "destroyed": ["${messageId.serialize}"]
| }, "c1"],
| ["Email/get", {
@@ -5364,23 +5381,25 @@ trait EmailSetMethodContract {
.body
.asString
- assertThatJson(response).isEqualTo(
- s"""{
- | "sessionState": "${SESSION_STATE.value}",
- | "methodResponses": [
- | ["Email/set", {
- | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6",
- | "newState": "${INSTANCE.value}",
- | "destroyed": ["${messageId.serialize}"],
- | "notDestroyed": {
- | "invalid": {
- | "type": "invalidArguments",
- | "description": "invalid is not a messageId: ${invalidMessageIdMessage("invalid")}"
- | }
- | }
- | }, "c1"]
- | ]
- |}""".stripMargin)
+ assertThatJson(response)
+ .whenIgnoringPaths("methodResponses[0][1].oldState",
+ "methodResponses[0][1].newState")
+ .isEqualTo(
+ s"""{
+ | "sessionState": "${SESSION_STATE.value}",
+ | "methodResponses": [
+ | ["Email/set", {
+ | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6",
+ | "destroyed": ["${messageId.serialize}"],
+ | "notDestroyed": {
+ | "invalid": {
+ | "type": "invalidArguments",
+ | "description": "invalid is not a messageId: ${invalidMessageIdMessage("invalid")}"
+ | }
+ | }
+ | }, "c1"]
+ | ]
+ |}""".stripMargin)
}
@Test
@@ -5434,7 +5453,9 @@ trait EmailSetMethodContract {
.asString
assertThatJson(response)
- .whenIgnoringPaths("methodResponses[1][1].state")
+ .whenIgnoringPaths("methodResponses[0][1].oldState",
+ "methodResponses[0][1].newState",
+ "methodResponses[1][1].state")
.isEqualTo(
s"""{
| "sessionState": "${SESSION_STATE.value}",
@@ -5523,14 +5544,15 @@ trait EmailSetMethodContract {
.asString
assertThatJson(response)
- .whenIgnoringPaths("methodResponses[1][1].state")
+ .whenIgnoringPaths("methodResponses[0][1].oldState",
+ "methodResponses[0][1].newState",
+ "methodResponses[1][1].state")
.isEqualTo(
s"""{
| "sessionState": "${SESSION_STATE.value}",
| "methodResponses": [
| ["Email/set", {
| "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6",
- | "newState": "${INSTANCE.value}",
| "updated": {
| "${messageId1.serialize}": null,
| "${messageId2.serialize}": null
@@ -5603,13 +5625,14 @@ trait EmailSetMethodContract {
.asString
assertThatJson(response)
+ .whenIgnoringPaths("methodResponses[0][1].oldState",
+ "methodResponses[0][1].newState")
.isEqualTo(
s"""{
| "sessionState": "${SESSION_STATE.value}",
| "methodResponses": [
| ["Email/set", {
| "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6",
- | "newState": "${INSTANCE.value}",
| "notUpdated": {
| "${messageId.serialize}": {
| "type": "notFound",
@@ -5675,7 +5698,9 @@ trait EmailSetMethodContract {
.asString
assertThatJson(response)
- .whenIgnoringPaths("methodResponses[1][1].state")
+ .whenIgnoringPaths("methodResponses[0][1].oldState",
+ "methodResponses[0][1].newState",
+ "methodResponses[1][1].state")
.isEqualTo(
s"""{
| "sessionState": "${SESSION_STATE.value}",
@@ -5760,13 +5785,14 @@ trait EmailSetMethodContract {
.asString
assertThatJson(response)
+ .whenIgnoringPaths("methodResponses[0][1].oldState",
+ "methodResponses[0][1].newState")
.isEqualTo(
s"""{
| "sessionState": "${SESSION_STATE.value}",
| "methodResponses": [
| ["Email/set", {
| "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6",
- | "newState": "${INSTANCE.value}",
| "notUpdated": {
| "${messageId.serialize}": {
| "type": "notFound",
@@ -5846,14 +5872,15 @@ trait EmailSetMethodContract {
.asString
assertThatJson(response)
- .whenIgnoringPaths("methodResponses[1][1].state")
+ .whenIgnoringPaths("methodResponses[0][1].oldState",
+ "methodResponses[0][1].newState",
+ "methodResponses[1][1].state")
.isEqualTo(
s"""{
| "sessionState": "${SESSION_STATE.value}",
| "methodResponses": [
| ["Email/set", {
| "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6",
- | "newState": "${INSTANCE.value}",
| "updated": {
| "${messageId.serialize}": null
| }
@@ -5929,14 +5956,15 @@ trait EmailSetMethodContract {
.asString
assertThatJson(response)
- .whenIgnoringPaths("methodResponses[1][1].state")
+ .whenIgnoringPaths("methodResponses[0][1].oldState",
+ "methodResponses[0][1].newState",
+ "methodResponses[1][1].state")
.isEqualTo(
s"""{
| "sessionState": "${SESSION_STATE.value}",
| "methodResponses": [
| ["Email/set", {
| "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6",
- | "newState": "${INSTANCE.value}",
| "updated": {
| "${messageId.serialize}": null
| }
@@ -6006,13 +6034,14 @@ trait EmailSetMethodContract {
.asString
assertThatJson(response)
+ .whenIgnoringPaths("methodResponses[0][1].oldState",
+ "methodResponses[0][1].newState")
.isEqualTo(
s"""{
| "sessionState": "${SESSION_STATE.value}",
| "methodResponses": [
| ["Email/set", {
| "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6",
- | "newState": "${INSTANCE.value}",
| "updated": {
| "${messageId.serialize}": null
| }
@@ -6069,13 +6098,14 @@ trait EmailSetMethodContract {
.asString
assertThatJson(response)
+ .whenIgnoringPaths("methodResponses[0][1].oldState",
+ "methodResponses[0][1].newState")
.isEqualTo(
s"""{
| "sessionState": "${SESSION_STATE.value}",
| "methodResponses": [
| ["Email/set", {
| "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6",
- | "newState": "${INSTANCE.value}",
| "notUpdated": {
| "${messageId.serialize}": {
| "type": "invalidPatch",
@@ -6130,13 +6160,14 @@ trait EmailSetMethodContract {
.asString
assertThatJson(response)
+ .whenIgnoringPaths("methodResponses[0][1].oldState",
+ "methodResponses[0][1].newState")
.isEqualTo(
s"""{
| "sessionState": "${SESSION_STATE.value}",
| "methodResponses": [
| ["Email/set", {
| "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6",
- | "newState": "${INSTANCE.value}",
| "notUpdated": {
| "${messageId.serialize}": {
| "type": "invalidPatch",
@@ -6191,13 +6222,14 @@ trait EmailSetMethodContract {
.asString
assertThatJson(response)
+ .whenIgnoringPaths("methodResponses[0][1].oldState",
+ "methodResponses[0][1].newState")
.isEqualTo(
s"""{
| "sessionState": "${SESSION_STATE.value}",
| "methodResponses": [
| ["Email/set", {
| "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6",
- | "newState": "${INSTANCE.value}",
| "notUpdated": {
| "${messageId.serialize}": {
| "type": "invalidPatch",
@@ -6269,13 +6301,14 @@ trait EmailSetMethodContract {
.asString
assertThatJson(response)
+ .whenIgnoringPaths("methodResponses[0][1].oldState",
+ "methodResponses[0][1].newState")
.isEqualTo(
s"""{
| "sessionState": "${SESSION_STATE.value}",
| "methodResponses": [
| ["Email/set", {
| "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6",
- | "newState": "${INSTANCE.value}",
| "updated": {
| "${messageId1.serialize}": null
| },
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/EmailSubmissionSetMethodContract.scala b/server/protocols/jmap-rfc-8621-integration-tests/jmap-rfc-8621-integration-tests-common/src/main/scala/org/apache/james/jmap/rfc8621/contract/EmailSubmissionSetMethodContract.scala
index 4ea493c..6e27196 100644
--- a/server/protocols/jmap-rfc-8621-integration-tests/jmap-rfc-8621-integration-tests-common/src/main/scala/org/apache/james/jmap/rfc8621/contract/EmailSubmissionSetMethodContract.scala
+++ b/server/protocols/jmap-rfc-8621-integration-tests/jmap-rfc-8621-integration-tests-common/src/main/scala/org/apache/james/jmap/rfc8621/contract/EmailSubmissionSetMethodContract.scala
@@ -886,6 +886,8 @@ trait EmailSubmissionSetMethodContract {
assertThatJson(response)
// Ids are randomly generated, and not stored, let's ignore it
.whenIgnoringPaths("methodResponses[0][1].created.k1490",
+ "methodResponses[1][1].newState",
+ "methodResponses[1][1].oldState",
"methodResponses[2][1].state")
.isEqualTo(s"""{
| "sessionState": "${SESSION_STATE.value}",
@@ -988,6 +990,8 @@ trait EmailSubmissionSetMethodContract {
assertThatJson(response)
// Ids are randomly generated, and not stored, let's ignore it
.whenIgnoringPaths("methodResponses[0][1].created.k1490",
+ "methodResponses[1][1].newState",
+ "methodResponses[1][1].oldState",
"methodResponses[2][1].state")
.isEqualTo(s"""{
| "sessionState": "${SESSION_STATE.value}",
---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscribe@james.apache.org
For additional commands, e-mail: notifications-help@james.apache.org
[james-project] 01/11: JAMES-3436 Email/set method contract fix up
Posted by rc...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
rcordier pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/james-project.git
commit c2cd494742565bb6d62c7f5a115ca78555bf7889
Author: LanKhuat <dl...@linagora.com>
AuthorDate: Wed Jan 13 11:34:46 2021 +0700
JAMES-3436 Email/set method contract fix up
---
.../apache/james/jmap/rfc8621/contract/EmailSetMethodContract.scala | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
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/EmailSetMethodContract.scala b/server/protocols/jmap-rfc-8621-integration-tests/jmap-rfc-8621-integration-tests-common/src/main/scala/org/apache/james/jmap/rfc8621/contract/EmailSetMethodContract.scala
index 57285ac..b39614d 100644
--- a/server/protocols/jmap-rfc-8621-integration-tests/jmap-rfc-8621-integration-tests-common/src/main/scala/org/apache/james/jmap/rfc8621/contract/EmailSetMethodContract.scala
+++ b/server/protocols/jmap-rfc-8621-integration-tests/jmap-rfc-8621-integration-tests-common/src/main/scala/org/apache/james/jmap/rfc8621/contract/EmailSetMethodContract.scala
@@ -6085,7 +6085,7 @@ trait EmailSetMethodContract {
| "notUpdated": {
| "${messageId.serialize}": {
| "type": "invalidPatch",
- | "description": "Message update is invalid: List((,List(JsonValidationError(List(Value associated with mailboxIds is invalid: List((/${messageId.serialize},List(JsonValidationError(List(Expecting mailboxId value to be a boolean),ArraySeq()))))),ArraySeq()))))"
+ | "description": "Message update is invalid: List((,List(JsonValidationError(List(Value associated with mailboxIds is invalid: List((/${mailboxId.serialize},List(JsonValidationError(List(Expecting mailboxId value to be a boolean),ArraySeq()))))),ArraySeq()))))"
| }
| }
| }, "c1"]
@@ -6146,7 +6146,7 @@ trait EmailSetMethodContract {
| "notUpdated": {
| "${messageId.serialize}": {
| "type": "invalidPatch",
- | "description": "Message update is invalid: List((,List(JsonValidationError(List(Value associated with mailboxIds is invalid: List((/${messageId.serialize},List(JsonValidationError(List(Expecting mailboxId value to be a boolean),ArraySeq()))))),ArraySeq()))))"
+ | "description": "Message update is invalid: List((,List(JsonValidationError(List(Value associated with mailboxIds is invalid: List((/${mailboxId.serialize},List(JsonValidationError(List(Expecting mailboxId value to be a boolean),ArraySeq()))))),ArraySeq()))))"
| }
| }
| }, "c1"]
---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscribe@james.apache.org
For additional commands, e-mail: notifications-help@james.apache.org
[james-project] 05/11: JAMES-3474 Disable asynchronous state tests
for distributed environment
Posted by rc...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
rcordier pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/james-project.git
commit c4d993331ee071b25584cbe12940ba2ee5728a7a
Author: LanKhuat <dl...@linagora.com>
AuthorDate: Tue Jan 12 11:02:46 2021 +0700
JAMES-3474 Disable asynchronous state tests for distributed environment
---
.../rfc8621/distributed/DistributedEmailSetMethodTest.java | 13 +++++++++++++
1 file changed, 13 insertions(+)
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/DistributedEmailSetMethodTest.java b/server/protocols/jmap-rfc-8621-integration-tests/distributed-jmap-rfc-8621-integration-tests/src/test/java/org/apache/james/jmap/rfc8621/distributed/DistributedEmailSetMethodTest.java
index ec07ea6..b103eac 100644
--- a/server/protocols/jmap-rfc-8621-integration-tests/distributed-jmap-rfc-8621-integration-tests/src/test/java/org/apache/james/jmap/rfc8621/distributed/DistributedEmailSetMethodTest.java
+++ b/server/protocols/jmap-rfc-8621-integration-tests/distributed-jmap-rfc-8621-integration-tests/src/test/java/org/apache/james/jmap/rfc8621/distributed/DistributedEmailSetMethodTest.java
@@ -23,6 +23,7 @@ import org.apache.james.CassandraExtension;
import org.apache.james.CassandraRabbitMQJamesConfiguration;
import org.apache.james.CassandraRabbitMQJamesServerMain;
import org.apache.james.DockerElasticSearchExtension;
+import org.apache.james.GuiceJamesServer;
import org.apache.james.JamesServerBuilder;
import org.apache.james.JamesServerExtension;
import org.apache.james.jmap.rfc8621.contract.EmailSetMethodContract;
@@ -32,6 +33,8 @@ import org.apache.james.modules.AwsS3BlobStoreExtension;
import org.apache.james.modules.RabbitMQExtension;
import org.apache.james.modules.TestJMAPServerModule;
import org.apache.james.modules.blobstore.BlobStoreConfiguration;
+import org.junit.jupiter.api.Disabled;
+import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;
import com.datastax.driver.core.utils.UUIDs;
@@ -67,4 +70,14 @@ public class DistributedEmailSetMethodTest implements EmailSetMethodContract {
public String invalidMessageIdMessage(String invalid) {
return String.format("Invalid UUID string: %s", invalid);
}
+
+ @Override
+ @Test
+ @Disabled("Distributed event bus is asynchronous, we cannot expect the newState to be returned immediately after Email/set call")
+ public void newStateShouldBeUpToDate(GuiceJamesServer server) {}
+
+ @Override
+ @Test
+ @Disabled("Distributed event bus is asynchronous, we cannot expect the newState to be returned immediately after Email/set call")
+ public void oldStateShouldIncludeSetChanges(GuiceJamesServer server) {}
}
---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscribe@james.apache.org
For additional commands, e-mail: notifications-help@james.apache.org
[james-project] 09/11: JAMES-3470 Adapt Email/set test for more
stability
Posted by rc...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
rcordier pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/james-project.git
commit 5de9000d9a8f7eff427ff9fb64c76f7a7e1361ce
Author: LanKhuat <dl...@linagora.com>
AuthorDate: Tue Jan 12 14:23:39 2021 +0700
JAMES-3470 Adapt Email/set test for more stability
---
.../rfc8621/contract/EmailSetMethodContract.scala | 48 ++++++++++++++--------
1 file changed, 30 insertions(+), 18 deletions(-)
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/EmailSetMethodContract.scala b/server/protocols/jmap-rfc-8621-integration-tests/jmap-rfc-8621-integration-tests-common/src/main/scala/org/apache/james/jmap/rfc8621/contract/EmailSetMethodContract.scala
index 55f1b10..9056fdd 100644
--- a/server/protocols/jmap-rfc-8621-integration-tests/jmap-rfc-8621-integration-tests-common/src/main/scala/org/apache/james/jmap/rfc8621/contract/EmailSetMethodContract.scala
+++ b/server/protocols/jmap-rfc-8621-integration-tests/jmap-rfc-8621-integration-tests-common/src/main/scala/org/apache/james/jmap/rfc8621/contract/EmailSetMethodContract.scala
@@ -23,6 +23,7 @@ import java.nio.charset.StandardCharsets
import java.time.ZonedDateTime
import java.time.format.DateTimeFormatter
import java.util.Date
+import java.util.concurrent.TimeUnit
import io.netty.handler.codec.http.HttpHeaderNames.ACCEPT
import io.restassured.RestAssured.{`given`, `with`, requestSpecification}
@@ -51,6 +52,8 @@ import org.apache.james.mime4j.dom.Message
import org.apache.james.modules.{ACLProbeImpl, MailboxProbeImpl}
import org.apache.james.utils.DataProbeImpl
import org.assertj.core.api.Assertions.assertThat
+import org.awaitility.Awaitility
+import org.awaitility.Duration.ONE_HUNDRED_MILLISECONDS
import org.hamcrest.Matchers.{equalTo, not}
import org.junit.jupiter.api.{BeforeEach, Test}
import org.junit.jupiter.params.ParameterizedTest
@@ -60,6 +63,12 @@ import play.api.libs.json.{JsNumber, JsString, Json}
import scala.jdk.CollectionConverters._
trait EmailSetMethodContract {
+ private lazy val slowPacedPollInterval = ONE_HUNDRED_MILLISECONDS
+ private lazy val calmlyAwait = Awaitility.`with`
+ .pollInterval(slowPacedPollInterval)
+ .and.`with`.pollDelay(slowPacedPollInterval)
+ .await
+ private lazy val awaitAtMostTenSeconds = calmlyAwait.atMost(10, TimeUnit.SECONDS)
private lazy val UTC_DATE_FORMAT = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ssX")
@BeforeEach
@@ -6546,24 +6555,27 @@ trait EmailSetMethodContract {
.build(message))
.getMessageId
- `given`
- .header(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER)
- .body(s"""{
- | "using": [
- | "urn:ietf:params:jmap:core",
- | "urn:ietf:params:jmap:mail",
- | "urn:apache:james:params:jmap:mail:shares"],
- | "methodCalls": [
- | ["Email/set", {
- | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6"
- | }, "c1"]
- | ]
- |}""".stripMargin)
- .when
- .post
- .`then`
- .statusCode(SC_OK)
- .body("methodResponses[0][1].oldState", not(equalTo(state)))
+ awaitAtMostTenSeconds.untilAsserted { () =>
+ `given`
+ .header(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER)
+ .body(
+ s"""{
+ | "using": [
+ | "urn:ietf:params:jmap:core",
+ | "urn:ietf:params:jmap:mail",
+ | "urn:apache:james:params:jmap:mail:shares"],
+ | "methodCalls": [
+ | ["Email/set", {
+ | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6"
+ | }, "c1"]
+ | ]
+ |}""".stripMargin)
+ .when
+ .post
+ .`then`
+ .statusCode(SC_OK)
+ .body("methodResponses[0][1].oldState", not(equalTo(state)))
+ }
}
private def buildTestMessage = {
---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscribe@james.apache.org
For additional commands, e-mail: notifications-help@james.apache.org
[james-project] 11/11: JAMES-3472 Add EmailChangesMethod
integration test for distributed environment
Posted by rc...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
rcordier pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/james-project.git
commit b929cdbdbb544c4fc800609b790f7e12efc628a0
Author: LanKhuat <dl...@linagora.com>
AuthorDate: Mon Jan 11 11:54:41 2021 +0700
JAMES-3472 Add EmailChangesMethod integration test for distributed environment
---
.../DistributedEmailChangeMethodTest.java | 60 ++++++++++++++++++++++
.../contract/EmailChangesMethodContract.scala | 4 +-
2 files changed, 63 insertions(+), 1 deletion(-)
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/DistributedEmailChangeMethodTest.java b/server/protocols/jmap-rfc-8621-integration-tests/distributed-jmap-rfc-8621-integration-tests/src/test/java/org/apache/james/jmap/rfc8621/distributed/DistributedEmailChangeMethodTest.java
new file mode 100644
index 0000000..d471d81
--- /dev/null
+++ b/server/protocols/jmap-rfc-8621-integration-tests/distributed-jmap-rfc-8621-integration-tests/src/test/java/org/apache/james/jmap/rfc8621/distributed/DistributedEmailChangeMethodTest.java
@@ -0,0 +1,60 @@
+/****************************************************************
+ * 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.rfc8621.distributed;
+
+import org.apache.james.CassandraExtension;
+import org.apache.james.CassandraRabbitMQJamesConfiguration;
+import org.apache.james.CassandraRabbitMQJamesServerMain;
+import org.apache.james.DockerElasticSearchExtension;
+import org.apache.james.JamesServerBuilder;
+import org.apache.james.JamesServerExtension;
+import org.apache.james.jmap.api.change.State;
+import org.apache.james.jmap.cassandra.change.CassandraStateFactory;
+import org.apache.james.jmap.rfc8621.contract.EmailChangesMethodContract;
+import org.apache.james.modules.AwsS3BlobStoreExtension;
+import org.apache.james.modules.RabbitMQExtension;
+import org.apache.james.modules.TestJMAPServerModule;
+import org.apache.james.modules.blobstore.BlobStoreConfiguration;
+import org.junit.jupiter.api.extension.RegisterExtension;
+
+public class DistributedEmailChangeMethodTest implements EmailChangesMethodContract {
+ @RegisterExtension
+ static JamesServerExtension testExtension = new JamesServerBuilder<CassandraRabbitMQJamesConfiguration>(tmpDir ->
+ CassandraRabbitMQJamesConfiguration.builder()
+ .workingDirectory(tmpDir)
+ .configurationFromClasspath()
+ .blobStore(BlobStoreConfiguration.builder()
+ .s3()
+ .disableCache()
+ .deduplication())
+ .build())
+ .extension(new DockerElasticSearchExtension())
+ .extension(new CassandraExtension())
+ .extension(new RabbitMQExtension())
+ .extension(new AwsS3BlobStoreExtension())
+ .server(configuration -> CassandraRabbitMQJamesServerMain.createServer(configuration)
+ .overrideWith(new TestJMAPServerModule()))
+ .build();
+
+ @Override
+ public State.Factory stateFactory() {
+ return new CassandraStateFactory();
+ }
+}
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/EmailChangesMethodContract.scala b/server/protocols/jmap-rfc-8621-integration-tests/jmap-rfc-8621-integration-tests-common/src/main/scala/org/apache/james/jmap/rfc8621/contract/EmailChangesMethodContract.scala
index 2f65896..83d050d 100644
--- a/server/protocols/jmap-rfc-8621-integration-tests/jmap-rfc-8621-integration-tests-common/src/main/scala/org/apache/james/jmap/rfc8621/contract/EmailChangesMethodContract.scala
+++ b/server/protocols/jmap-rfc-8621-integration-tests/jmap-rfc-8621-integration-tests-common/src/main/scala/org/apache/james/jmap/rfc8621/contract/EmailChangesMethodContract.scala
@@ -40,7 +40,7 @@ import org.apache.james.jmap.http.UserCredential
import org.apache.james.jmap.rfc8621.contract.Fixture.{ACCEPT_RFC8621_VERSION_HEADER, ANDRE, ANDRE_ACCOUNT_ID, ANDRE_PASSWORD, BOB, BOB_PASSWORD, DOMAIN, authScheme, baseRequestSpecBuilder}
import org.apache.james.mailbox.MessageManager.AppendCommand
import org.apache.james.mailbox.model.MailboxACL.Right
-import org.apache.james.mailbox.model.{MailboxACL, MailboxId, MailboxPath, MessageId}
+import org.apache.james.mailbox.model.{MailboxACL, MailboxPath, MessageId}
import org.apache.james.mime4j.dom.Message
import org.apache.james.modules.{ACLProbeImpl, MailboxProbeImpl}
import org.apache.james.utils.DataProbeImpl
@@ -971,6 +971,8 @@ trait EmailChangesMethodContract {
.build
mailboxProbe.appendMessage(BOB.asString(), path, AppendCommand.from(message))
+ waitForNextState(server, AccountId.fromUsername(BOB), State.INITIAL)
+
val request1 =
s"""{
| "using": ["urn:ietf:params:jmap:core", "urn:ietf:params:jmap:mail"],
---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscribe@james.apache.org
For additional commands, e-mail: notifications-help@james.apache.org
[james-project] 10/11: JAMES-3472 Remove unused method
Posted by rc...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
rcordier pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/james-project.git
commit a046adfc27f8b6cfd5517e47e053b6d3c472ae0d
Author: LanKhuat <dl...@linagora.com>
AuthorDate: Mon Jan 11 11:53:42 2021 +0700
JAMES-3472 Remove unused method
---
.../james/jmap/rfc8621/contract/EmailChangesMethodContract.scala | 1 -
.../james/jmap/rfc8621/memory/MemoryEmailChangesMethodTest.java | 9 ---------
2 files changed, 10 deletions(-)
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/EmailChangesMethodContract.scala b/server/protocols/jmap-rfc-8621-integration-tests/jmap-rfc-8621-integration-tests-common/src/main/scala/org/apache/james/jmap/rfc8621/contract/EmailChangesMethodContract.scala
index 0817ebb..2f65896 100644
--- a/server/protocols/jmap-rfc-8621-integration-tests/jmap-rfc-8621-integration-tests-common/src/main/scala/org/apache/james/jmap/rfc8621/contract/EmailChangesMethodContract.scala
+++ b/server/protocols/jmap-rfc-8621-integration-tests/jmap-rfc-8621-integration-tests-common/src/main/scala/org/apache/james/jmap/rfc8621/contract/EmailChangesMethodContract.scala
@@ -60,7 +60,6 @@ trait EmailChangesMethodContract {
private lazy val awaitAtMostTenSeconds = calmlyAwait.atMost(10, TimeUnit.SECONDS)
def stateFactory: State.Factory
- def generateMailboxId: MailboxId
@BeforeEach
def setUp(server: GuiceJamesServer): Unit = {
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/MemoryEmailChangesMethodTest.java b/server/protocols/jmap-rfc-8621-integration-tests/memory-jmap-rfc-8621-integration-tests/src/test/java/org/apache/james/jmap/rfc8621/memory/MemoryEmailChangesMethodTest.java
index a0ce35a..79634b0 100644
--- a/server/protocols/jmap-rfc-8621-integration-tests/memory-jmap-rfc-8621-integration-tests/src/test/java/org/apache/james/jmap/rfc8621/memory/MemoryEmailChangesMethodTest.java
+++ b/server/protocols/jmap-rfc-8621-integration-tests/memory-jmap-rfc-8621-integration-tests/src/test/java/org/apache/james/jmap/rfc8621/memory/MemoryEmailChangesMethodTest.java
@@ -21,15 +21,11 @@ package org.apache.james.jmap.rfc8621.memory;
import static org.apache.james.MemoryJamesServerMain.IN_MEMORY_SERVER_AGGREGATE_MODULE;
-import java.util.concurrent.ThreadLocalRandom;
-
import org.apache.james.GuiceJamesServer;
import org.apache.james.JamesServerBuilder;
import org.apache.james.JamesServerExtension;
import org.apache.james.jmap.api.change.State;
import org.apache.james.jmap.rfc8621.contract.EmailChangesMethodContract;
-import org.apache.james.mailbox.inmemory.InMemoryId;
-import org.apache.james.mailbox.model.MailboxId;
import org.apache.james.modules.TestJMAPServerModule;
import org.junit.jupiter.api.extension.RegisterExtension;
@@ -45,9 +41,4 @@ public class MemoryEmailChangesMethodTest implements EmailChangesMethodContract
public State.Factory stateFactory() {
return State.Factory.DEFAULT;
}
-
- @Override
- public MailboxId generateMailboxId() {
- return InMemoryId.of(ThreadLocalRandom.current().nextInt());
- }
}
---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscribe@james.apache.org
For additional commands, e-mail: notifications-help@james.apache.org
[james-project] 08/11: JAMES-3470 EmailChangeRepositoryContract
should stop relying on TestMessageId
Posted by rc...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
rcordier pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/james-project.git
commit 4c16e1ff84299fefea9ffe58bcea54ff2e7f0029
Author: LanKhuat <dl...@linagora.com>
AuthorDate: Mon Jan 11 11:39:37 2021 +0700
JAMES-3470 EmailChangeRepositoryContract should stop relying on TestMessageId
---
.../mailbox/cassandra/ids/CassandraMessageId.java | 2 +-
.../change/CassandraEmailChangeRepositoryTest.java | 13 +
.../api/change/EmailChangeRepositoryContract.java | 699 +++++++++++++--------
.../change/MemoryEmailChangeRepositoryTest.java | 16 +-
4 files changed, 462 insertions(+), 268 deletions(-)
diff --git a/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/ids/CassandraMessageId.java b/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/ids/CassandraMessageId.java
index cf7cb63..12be3fd 100644
--- a/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/ids/CassandraMessageId.java
+++ b/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/ids/CassandraMessageId.java
@@ -36,7 +36,7 @@ public class CassandraMessageId implements MessageId {
return of(UUIDs.timeBased());
}
- public CassandraMessageId of(UUID uuid) {
+ public static CassandraMessageId of(UUID uuid) {
return new CassandraMessageId(uuid);
}
diff --git a/server/data/data-jmap-cassandra/src/test/java/org/apache/james/jmap/cassandra/change/CassandraEmailChangeRepositoryTest.java b/server/data/data-jmap-cassandra/src/test/java/org/apache/james/jmap/cassandra/change/CassandraEmailChangeRepositoryTest.java
index 50af3ff..8094155 100644
--- a/server/data/data-jmap-cassandra/src/test/java/org/apache/james/jmap/cassandra/change/CassandraEmailChangeRepositoryTest.java
+++ b/server/data/data-jmap-cassandra/src/test/java/org/apache/james/jmap/cassandra/change/CassandraEmailChangeRepositoryTest.java
@@ -26,6 +26,9 @@ import org.apache.james.backends.cassandra.init.CassandraZonedDateTimeModule;
import org.apache.james.backends.cassandra.versions.CassandraSchemaVersionModule;
import org.apache.james.jmap.api.change.EmailChangeRepository;
import org.apache.james.jmap.api.change.EmailChangeRepositoryContract;
+import org.apache.james.jmap.api.change.State;
+import org.apache.james.mailbox.cassandra.ids.CassandraMessageId;
+import org.apache.james.mailbox.model.MessageId;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.extension.RegisterExtension;
@@ -50,4 +53,14 @@ public class CassandraEmailChangeRepositoryTest implements EmailChangeRepository
public EmailChangeRepository emailChangeRepository() {
return emailChangeRepository;
}
+
+ @Override
+ public State generateNewState() {
+ return new CassandraStateFactory().generate();
+ }
+
+ @Override
+ public MessageId generateNewMessageId() {
+ return new CassandraMessageId.Factory().generate();
+ }
}
diff --git a/server/data/data-jmap/src/test/java/org/apache/james/jmap/api/change/EmailChangeRepositoryContract.java b/server/data/data-jmap/src/test/java/org/apache/james/jmap/api/change/EmailChangeRepositoryContract.java
index fc0ac24..bf0ca99 100644
--- a/server/data/data-jmap/src/test/java/org/apache/james/jmap/api/change/EmailChangeRepositoryContract.java
+++ b/server/data/data-jmap/src/test/java/org/apache/james/jmap/api/change/EmailChangeRepositoryContract.java
@@ -26,20 +26,20 @@ import static org.assertj.core.api.Assertions.assertThatThrownBy;
import java.time.ZonedDateTime;
import java.util.Optional;
-import java.util.UUID;
import org.apache.james.jmap.api.exception.ChangeNotFoundException;
import org.apache.james.jmap.api.model.AccountId;
-import org.apache.james.mailbox.model.TestMessageId;
+import org.apache.james.mailbox.model.MessageId;
import org.assertj.core.api.SoftAssertions;
import org.junit.jupiter.api.Test;
public interface EmailChangeRepositoryContract {
AccountId ACCOUNT_ID = AccountId.fromUsername(BOB);
ZonedDateTime DATE = ZonedDateTime.now();
- State STATE_0 = State.of(UUID.randomUUID());
EmailChangeRepository emailChangeRepository();
+ MessageId generateNewMessageId();
+ State generateNewState();
@Test
default void saveChangeShouldSuccess() {
@@ -47,10 +47,10 @@ public interface EmailChangeRepositoryContract {
EmailChange change = EmailChange.builder()
.accountId(ACCOUNT_ID)
- .state(STATE_0)
+ .state(generateNewState())
.date(DATE)
.isDelegated(false)
- .created(TestMessageId.of(1))
+ .created(generateNewMessageId())
.build();
assertThatCode(() -> repository.save(change).block())
@@ -69,26 +69,30 @@ public interface EmailChangeRepositoryContract {
default void getLatestStateShouldReturnLastPersistedState() {
EmailChangeRepository repository = emailChangeRepository();
+ MessageId messageId1 = generateNewMessageId();
+ MessageId messageId2 = generateNewMessageId();
+ MessageId messageId3 = generateNewMessageId();
+
EmailChange change1 = EmailChange.builder()
.accountId(ACCOUNT_ID)
- .state(State.of(UUID.randomUUID()))
+ .state(generateNewState())
.date(DATE.minusHours(2))
.isDelegated(false)
- .created(TestMessageId.of(2))
+ .created(messageId1)
.build();
EmailChange change2 = EmailChange.builder()
.accountId(ACCOUNT_ID)
- .state(State.of(UUID.randomUUID()))
+ .state(generateNewState())
.date(DATE.minusHours(1))
.isDelegated(false)
- .created(TestMessageId.of(3))
+ .created(messageId2)
.build();
EmailChange change3 = EmailChange.builder()
.accountId(ACCOUNT_ID)
- .state(State.of(UUID.randomUUID()))
+ .state(generateNewState())
.date(DATE)
.isDelegated(false)
- .created(TestMessageId.of(4))
+ .created(messageId3)
.build();
repository.save(change1).block();
repository.save(change2).block();
@@ -102,26 +106,30 @@ public interface EmailChangeRepositoryContract {
default void getLatestStateShouldReturnLastNonDelegatedPersistedState() {
EmailChangeRepository repository = emailChangeRepository();
+ MessageId messageId1 = generateNewMessageId();
+ MessageId messageId2 = generateNewMessageId();
+ MessageId messageId3 = generateNewMessageId();
+
EmailChange change1 = EmailChange.builder()
.accountId(ACCOUNT_ID)
- .state(State.of(UUID.randomUUID()))
+ .state(generateNewState())
.date(DATE.minusHours(2))
.isDelegated(false)
- .created(TestMessageId.of(2))
+ .created(messageId1)
.build();
EmailChange change2 = EmailChange.builder()
.accountId(ACCOUNT_ID)
- .state(State.of(UUID.randomUUID()))
+ .state(generateNewState())
.date(DATE.minusHours(1))
.isDelegated(false)
- .created(TestMessageId.of(3))
+ .created(messageId2)
.build();
EmailChange change3 = EmailChange.builder()
.accountId(ACCOUNT_ID)
- .state(State.of(UUID.randomUUID()))
+ .state(generateNewState())
.date(DATE)
.isDelegated(true)
- .created(TestMessageId.of(4))
+ .created(messageId3)
.build();
repository.save(change1).block();
repository.save(change2).block();
@@ -135,41 +143,45 @@ public interface EmailChangeRepositoryContract {
default void getChangesShouldSuccess() {
EmailChangeRepository repository = emailChangeRepository();
+ MessageId messageId = generateNewMessageId();
+ State state = generateNewState();
+
EmailChange oldState = EmailChange.builder()
.accountId(ACCOUNT_ID)
- .state(STATE_0)
+ .state(state)
.date(DATE.minusHours(1))
.isDelegated(false)
- .created(TestMessageId.of(1))
+ .created(messageId)
.build();
EmailChange change = EmailChange.builder()
.accountId(ACCOUNT_ID)
- .state(State.of(UUID.randomUUID()))
+ .state(generateNewState())
.date(DATE)
.isDelegated(false)
- .updated(TestMessageId.of(1))
+ .updated(messageId)
.build();
repository.save(oldState).block();
repository.save(change).block();
- assertThat(repository.getSinceState(ACCOUNT_ID, STATE_0, Optional.empty()).block().getAllChanges())
+ assertThat(repository.getSinceState(ACCOUNT_ID, state, Optional.empty()).block().getAllChanges())
.hasSameElementsAs(change.getUpdated());
}
@Test
default void getChangesShouldReturnEmptyWhenNoNewerState() {
EmailChangeRepository repository = emailChangeRepository();
+ State state = generateNewState();
EmailChange oldState = EmailChange.builder()
.accountId(ACCOUNT_ID)
- .state(STATE_0)
+ .state(state)
.date(DATE.minusHours(1))
.isDelegated(false)
- .created(TestMessageId.of(1))
+ .created(generateNewMessageId())
.build();
repository.save(oldState).block();
- assertThat(repository.getSinceState(ACCOUNT_ID, STATE_0, Optional.empty()).block().getAllChanges())
+ assertThat(repository.getSinceState(ACCOUNT_ID, state, Optional.empty()).block().getAllChanges())
.isEmpty();
}
@@ -177,16 +189,18 @@ public interface EmailChangeRepositoryContract {
default void getChangesShouldReturnCurrentStateWhenNoNewerState() {
EmailChangeRepository repository = emailChangeRepository();
+ State state = generateNewState();
+
EmailChange oldState = EmailChange.builder()
.accountId(ACCOUNT_ID)
- .state(STATE_0)
+ .state(state)
.date(DATE.minusHours(1))
.isDelegated(false)
- .created(TestMessageId.of(1))
+ .created(generateNewMessageId())
.build();
repository.save(oldState).block();
- assertThat(repository.getSinceState(ACCOUNT_ID, STATE_0, Optional.empty()).block().getNewState())
+ assertThat(repository.getSinceState(ACCOUNT_ID, state, Optional.empty()).block().getNewState())
.isEqualTo(oldState.getState());
}
@@ -194,40 +208,47 @@ public interface EmailChangeRepositoryContract {
default void getChangesShouldLimitChanges() {
EmailChangeRepository repository = emailChangeRepository();
+ State state = generateNewState();
+ MessageId messageId1 = generateNewMessageId();
+ MessageId messageId2 = generateNewMessageId();
+ MessageId messageId3 = generateNewMessageId();
+ MessageId messageId4 = generateNewMessageId();
+ MessageId messageId5 = generateNewMessageId();
+
EmailChange oldState = EmailChange.builder()
.accountId(ACCOUNT_ID)
- .state(STATE_0)
+ .state(state)
.date(DATE.minusHours(3))
.isDelegated(false)
- .created(TestMessageId.of(1))
+ .created(messageId1)
.build();
EmailChange change1 = EmailChange.builder()
.accountId(ACCOUNT_ID)
- .state(State.of(UUID.randomUUID()))
+ .state(generateNewState())
.date(DATE.minusHours(2))
.isDelegated(false)
- .created(TestMessageId.of(2))
+ .created(messageId2)
.build();
EmailChange change2 = EmailChange.builder()
.accountId(ACCOUNT_ID)
- .state(State.of(UUID.randomUUID()))
+ .state(generateNewState())
.date(DATE.minusHours(1))
.isDelegated(false)
- .created(TestMessageId.of(3))
+ .created(messageId3)
.build();
EmailChange change3 = EmailChange.builder()
.accountId(ACCOUNT_ID)
- .state(State.of(UUID.randomUUID()))
+ .state(generateNewState())
.date(DATE)
.isDelegated(false)
- .created(TestMessageId.of(4))
+ .created(messageId4)
.build();
EmailChange change4 = EmailChange.builder()
.accountId(ACCOUNT_ID)
- .state(State.of(UUID.randomUUID()))
+ .state(generateNewState())
.date(DATE.plusHours(1))
.isDelegated(false)
- .created(TestMessageId.of(5))
+ .created(messageId5)
.build();
repository.save(oldState).block();
repository.save(change1).block();
@@ -235,41 +256,47 @@ public interface EmailChangeRepositoryContract {
repository.save(change3).block();
repository.save(change4).block();
- assertThat(repository.getSinceState(ACCOUNT_ID, STATE_0, Optional.of(Limit.of(3))).block().getCreated())
- .containsExactlyInAnyOrder(TestMessageId.of(2), TestMessageId.of(3), TestMessageId.of(4));
+ assertThat(repository.getSinceState(ACCOUNT_ID, state, Optional.of(Limit.of(3))).block().getCreated())
+ .containsExactlyInAnyOrder(messageId2, messageId3, messageId4);
}
@Test
default void getChangesShouldReturnAllFromInitial() {
EmailChangeRepository repository = emailChangeRepository();
+ State state = generateNewState();
+ MessageId messageId1 = generateNewMessageId();
+ MessageId messageId2 = generateNewMessageId();
+ MessageId messageId3 = generateNewMessageId();
+ MessageId messageId4 = generateNewMessageId();
+
EmailChange oldState = EmailChange.builder()
.accountId(ACCOUNT_ID)
- .state(STATE_0)
+ .state(state)
.date(DATE.minusHours(3))
.isDelegated(false)
- .created(TestMessageId.of(1))
+ .created(messageId1)
.build();
EmailChange change1 = EmailChange.builder()
.accountId(ACCOUNT_ID)
- .state(State.of(UUID.randomUUID()))
+ .state(generateNewState())
.date(DATE.minusHours(2))
.isDelegated(false)
- .created(TestMessageId.of(2))
+ .created(messageId2)
.build();
EmailChange change2 = EmailChange.builder()
.accountId(ACCOUNT_ID)
- .state(State.of(UUID.randomUUID()))
+ .state(generateNewState())
.date(DATE.minusHours(1))
.isDelegated(false)
- .created(TestMessageId.of(3))
+ .created(messageId3)
.build();
EmailChange change3 = EmailChange.builder()
.accountId(ACCOUNT_ID)
- .state(State.of(UUID.randomUUID()))
+ .state(generateNewState())
.date(DATE)
.isDelegated(false)
- .created(TestMessageId.of(4))
+ .created(messageId4)
.build();
repository.save(oldState).block();
repository.save(change1).block();
@@ -277,83 +304,102 @@ public interface EmailChangeRepositoryContract {
repository.save(change3).block();
assertThat(repository.getSinceState(ACCOUNT_ID, State.INITIAL, Optional.of(Limit.of(3))).block().getCreated())
- .containsExactlyInAnyOrder(TestMessageId.of(1), TestMessageId.of(2), TestMessageId.of(3));
+ .containsExactlyInAnyOrder(messageId1, messageId2, messageId3);
}
@Test
default void getChangesFromInitialShouldReturnNewState() {
EmailChangeRepository repository = emailChangeRepository();
- State state2 = State.of(UUID.randomUUID());
- EmailChange oldState = EmailChange.builder()
+ State state = generateNewState();
+ State state2 = generateNewState();
+ State state3 = generateNewState();
+ State state4 = generateNewState();
+
+ MessageId messageId1 = generateNewMessageId();
+ MessageId messageId2 = generateNewMessageId();
+ MessageId messageId3 = generateNewMessageId();
+ MessageId messageId4 = generateNewMessageId();
+
+ EmailChange change1 = EmailChange.builder()
.accountId(ACCOUNT_ID)
- .state(STATE_0)
+ .state(state)
.date(DATE.minusHours(3))
.isDelegated(false)
- .created(TestMessageId.of(1))
+ .created(messageId1)
.build();
- EmailChange change1 = EmailChange.builder()
+ EmailChange change2 = EmailChange.builder()
.accountId(ACCOUNT_ID)
- .state(State.of(UUID.randomUUID()))
+ .state(state2)
.date(DATE.minusHours(2))
.isDelegated(false)
- .created(TestMessageId.of(2))
+ .created(messageId2)
.build();
- EmailChange change2 = EmailChange.builder()
+ EmailChange change3 = EmailChange.builder()
.accountId(ACCOUNT_ID)
- .state(state2)
+ .state(state3)
.date(DATE.minusHours(1))
.isDelegated(false)
- .created(TestMessageId.of(3))
+ .created(messageId3)
.build();
- EmailChange change3 = EmailChange.builder()
+ EmailChange change4 = EmailChange.builder()
.accountId(ACCOUNT_ID)
- .state(State.of(UUID.randomUUID()))
+ .state(state4)
.date(DATE)
.isDelegated(false)
- .created(TestMessageId.of(4))
+ .created(messageId4)
.build();
- repository.save(oldState).block();
repository.save(change1).block();
repository.save(change2).block();
repository.save(change3).block();
+ repository.save(change4).block();
assertThat(repository.getSinceState(ACCOUNT_ID, State.INITIAL, Optional.of(Limit.of(3))).block().getNewState())
- .isEqualTo(state2);
+ .isEqualTo(state3);
}
@Test
default void getChangesShouldLimitChangesWhenMaxChangesOmitted() {
EmailChangeRepository repository = emailChangeRepository();
+ State state = generateNewState();
+
+ MessageId messageId1 = generateNewMessageId();
+ MessageId messageId2 = generateNewMessageId();
+ MessageId messageId3 = generateNewMessageId();
+ MessageId messageId4 = generateNewMessageId();
+ MessageId messageId5 = generateNewMessageId();
+ MessageId messageId6 = generateNewMessageId();
+ MessageId messageId7 = generateNewMessageId();
+
EmailChange oldState = EmailChange.builder()
.accountId(ACCOUNT_ID)
- .state(STATE_0)
+ .state(state)
.date(DATE.minusHours(2))
.isDelegated(false)
- .created(TestMessageId.of(1))
+ .created(messageId1)
.build();
EmailChange change1 = EmailChange.builder()
.accountId(ACCOUNT_ID)
- .state(State.of(UUID.randomUUID()))
+ .state(generateNewState())
.date(DATE.minusHours(1))
.isDelegated(false)
- .created(TestMessageId.of(2), TestMessageId.of(3), TestMessageId.of(4), TestMessageId.of(5), TestMessageId.of(6))
+ .created(messageId2, messageId3, messageId4, messageId5, messageId6)
.build();
EmailChange change2 = EmailChange.builder()
.accountId(ACCOUNT_ID)
- .state(State.of(UUID.randomUUID()))
+ .state(generateNewState())
.date(DATE)
.isDelegated(false)
- .created(TestMessageId.of(7))
+ .created(messageId7)
.build();
repository.save(oldState).block();
repository.save(change1).block();
repository.save(change2).block();
- assertThat(repository.getSinceState(ACCOUNT_ID, STATE_0, Optional.empty()).block().getAllChanges())
+ assertThat(repository.getSinceState(ACCOUNT_ID, state, Optional.empty()).block().getAllChanges())
.hasSameElementsAs(change1.getCreated());
}
@@ -361,32 +407,40 @@ public interface EmailChangeRepositoryContract {
default void getChangesShouldNotReturnMoreThanMaxChanges() {
EmailChangeRepository repository = emailChangeRepository();
+ State state = generateNewState();
+
+ MessageId messageId1 = generateNewMessageId();
+ MessageId messageId2 = generateNewMessageId();
+ MessageId messageId3 = generateNewMessageId();
+ MessageId messageId4 = generateNewMessageId();
+ MessageId messageId5 = generateNewMessageId();
+
EmailChange oldState = EmailChange.builder()
.accountId(ACCOUNT_ID)
- .state(STATE_0)
+ .state(state)
.date(DATE.minusHours(2))
.isDelegated(false)
- .created(TestMessageId.of(1))
+ .created(messageId1)
.build();
EmailChange change1 = EmailChange.builder()
.accountId(ACCOUNT_ID)
- .state(State.of(UUID.randomUUID()))
+ .state(generateNewState())
.date(DATE.minusHours(1))
.isDelegated(false)
- .created(TestMessageId.of(2), TestMessageId.of(3))
+ .created(messageId2, messageId3)
.build();
EmailChange change2 = EmailChange.builder()
.accountId(ACCOUNT_ID)
- .state(State.of(UUID.randomUUID()))
+ .state(generateNewState())
.date(DATE)
.isDelegated(false)
- .created(TestMessageId.of(4), TestMessageId.of(5))
+ .created(messageId4, messageId5)
.build();
repository.save(oldState).block();
repository.save(change1).block();
repository.save(change2).block();
- assertThat(repository.getSinceState(ACCOUNT_ID, STATE_0, Optional.of(Limit.of(3))).block().getAllChanges())
+ assertThat(repository.getSinceState(ACCOUNT_ID, state, Optional.of(Limit.of(3))).block().getAllChanges())
.hasSameElementsAs(change1.getCreated());
}
@@ -394,31 +448,39 @@ public interface EmailChangeRepositoryContract {
default void getChangesShouldReturnEmptyWhenNumberOfChangesExceedMaxChanges() {
EmailChangeRepository repository = emailChangeRepository();
+ State state = generateNewState();
+
+ MessageId messageId1 = generateNewMessageId();
+ MessageId messageId2 = generateNewMessageId();
+ MessageId messageId3 = generateNewMessageId();
+ MessageId messageId4 = generateNewMessageId();
+ MessageId messageId5 = generateNewMessageId();
+
EmailChange oldState = EmailChange.builder()
.accountId(ACCOUNT_ID)
- .state(STATE_0)
+ .state(state)
.date(DATE.minusHours(2))
.isDelegated(false)
- .created(TestMessageId.of(1))
+ .created(messageId1)
.build();
EmailChange change1 = EmailChange.builder()
.accountId(ACCOUNT_ID)
- .state(State.of(UUID.randomUUID()))
+ .state(generateNewState())
.date(DATE.minusHours(1))
.isDelegated(false)
- .created(TestMessageId.of(2), TestMessageId.of(3))
+ .created(messageId2, messageId3)
.build();
EmailChange change2 = EmailChange.builder()
.accountId(ACCOUNT_ID)
- .state(State.of(UUID.randomUUID()))
+ .state(generateNewState())
.date(DATE)
.isDelegated(false)
- .created(TestMessageId.of(4), TestMessageId.of(5))
+ .created(messageId4, messageId5)
.build();
repository.save(oldState).block();
repository.save(change1).block();
- assertThat(repository.getSinceState(ACCOUNT_ID, STATE_0, Optional.of(Limit.of(1))).block().getAllChanges())
+ assertThat(repository.getSinceState(ACCOUNT_ID, state, Optional.of(Limit.of(1))).block().getAllChanges())
.isEmpty();
}
@@ -426,32 +488,38 @@ public interface EmailChangeRepositoryContract {
default void getChangesShouldReturnNewState() {
EmailChangeRepository repository = emailChangeRepository();
+ State state = generateNewState();
+
+ MessageId messageId1 = generateNewMessageId();
+ MessageId messageId2 = generateNewMessageId();
+ MessageId messageId3 = generateNewMessageId();
+
EmailChange oldState = EmailChange.builder()
.accountId(ACCOUNT_ID)
- .state(STATE_0)
+ .state(state)
.date(DATE.minusHours(2))
.isDelegated(false)
- .created(TestMessageId.of(1))
+ .created(messageId1)
.build();
EmailChange change1 = EmailChange.builder()
.accountId(ACCOUNT_ID)
- .state(State.of(UUID.randomUUID()))
+ .state(generateNewState())
.date(DATE.minusHours(1))
.isDelegated(false)
- .created(TestMessageId.of(2), TestMessageId.of(3))
+ .created(messageId2, messageId3)
.build();
EmailChange change2 = EmailChange.builder()
.accountId(ACCOUNT_ID)
- .state(State.of(UUID.randomUUID()))
+ .state(generateNewState())
.date(DATE)
.isDelegated(false)
- .updated(TestMessageId.of(2), TestMessageId.of(3))
+ .updated(messageId2, messageId3)
.build();
repository.save(oldState).block();
repository.save(change1).block();
repository.save(change2).block();
- assertThat(repository.getSinceState(ACCOUNT_ID, STATE_0, Optional.empty()).block().getNewState())
+ assertThat(repository.getSinceState(ACCOUNT_ID, state, Optional.empty()).block().getNewState())
.isEqualTo(change2.getState());
}
@@ -459,32 +527,38 @@ public interface EmailChangeRepositoryContract {
default void hasMoreChangesShouldBeTrueWhenMoreChanges() {
EmailChangeRepository repository = emailChangeRepository();
+ State state = generateNewState();
+
+ MessageId messageId1 = generateNewMessageId();
+ MessageId messageId2 = generateNewMessageId();
+ MessageId messageId3 = generateNewMessageId();
+
EmailChange oldState = EmailChange.builder()
.accountId(ACCOUNT_ID)
- .state(STATE_0)
+ .state(state)
.date(DATE.minusHours(2))
.isDelegated(false)
- .created(TestMessageId.of(1))
+ .created(messageId1)
.build();
EmailChange change1 = EmailChange.builder()
.accountId(ACCOUNT_ID)
- .state(State.of(UUID.randomUUID()))
+ .state(generateNewState())
.date(DATE.minusHours(1))
.isDelegated(false)
- .created(TestMessageId.of(2), TestMessageId.of(3))
+ .created(messageId2, messageId3)
.build();
EmailChange change2 = EmailChange.builder()
.accountId(ACCOUNT_ID)
- .state(State.of(UUID.randomUUID()))
+ .state(generateNewState())
.date(DATE)
.isDelegated(false)
- .updated(TestMessageId.of(2), TestMessageId.of(3))
+ .updated(messageId2, messageId3)
.build();
repository.save(oldState).block();
repository.save(change1).block();
repository.save(change2).block();
- assertThat(repository.getSinceState(ACCOUNT_ID, STATE_0, Optional.of(Limit.of(1))).block().hasMoreChanges())
+ assertThat(repository.getSinceState(ACCOUNT_ID, state, Optional.of(Limit.of(1))).block().hasMoreChanges())
.isTrue();
}
@@ -492,32 +566,38 @@ public interface EmailChangeRepositoryContract {
default void hasMoreChangesShouldBeFalseWhenNoMoreChanges() {
EmailChangeRepository repository = emailChangeRepository();
+ State state = generateNewState();
+
+ MessageId messageId1 = generateNewMessageId();
+ MessageId messageId2 = generateNewMessageId();
+ MessageId messageId3 = generateNewMessageId();
+
EmailChange oldState = EmailChange.builder()
.accountId(ACCOUNT_ID)
- .state(STATE_0)
+ .state(state)
.date(DATE.minusHours(2))
.isDelegated(false)
- .created(TestMessageId.of(1))
+ .created(messageId1)
.build();
EmailChange change1 = EmailChange.builder()
.accountId(ACCOUNT_ID)
- .state(State.of(UUID.randomUUID()))
+ .state(generateNewState())
.date(DATE.minusHours(1))
.isDelegated(false)
- .created(TestMessageId.of(2), TestMessageId.of(3))
+ .created(messageId2, messageId3)
.build();
EmailChange change2 = EmailChange.builder()
.accountId(ACCOUNT_ID)
- .state(State.of(UUID.randomUUID()))
+ .state(generateNewState())
.date(DATE)
.isDelegated(false)
- .updated(TestMessageId.of(2), TestMessageId.of(3))
+ .updated(messageId2, messageId3)
.build();
repository.save(oldState).block();
repository.save(change1).block();
repository.save(change2).block();
- assertThat(repository.getSinceState(ACCOUNT_ID, STATE_0, Optional.of(Limit.of(4))).block().hasMoreChanges())
+ assertThat(repository.getSinceState(ACCOUNT_ID, state, Optional.of(Limit.of(4))).block().hasMoreChanges())
.isFalse();
}
@@ -525,50 +605,62 @@ public interface EmailChangeRepositoryContract {
default void changesShouldBeStoredInTheirRespectiveType() {
EmailChangeRepository repository = emailChangeRepository();
+ State state = generateNewState();
+
+ MessageId messageId1 = generateNewMessageId();
+ MessageId messageId2 = generateNewMessageId();
+ MessageId messageId3 = generateNewMessageId();
+ MessageId messageId4 = generateNewMessageId();
+ MessageId messageId5 = generateNewMessageId();
+ MessageId messageId6 = generateNewMessageId();
+ MessageId messageId7 = generateNewMessageId();
+ MessageId messageId8 = generateNewMessageId();
+ MessageId messageId9 = generateNewMessageId();
+ MessageId messageId10 = generateNewMessageId();
EmailChange oldState = EmailChange.builder()
.accountId(ACCOUNT_ID)
- .state(STATE_0)
+ .state(state)
.date(DATE.minusHours(3))
.isDelegated(false)
- .created(TestMessageId.of(1), TestMessageId.of(9), TestMessageId.of(10))
+ .created(messageId1, messageId9, messageId10)
.build();
EmailChange change1 = EmailChange.builder()
.accountId(ACCOUNT_ID)
- .state(State.of(UUID.randomUUID()))
+ .state(generateNewState())
.date(DATE.minusHours(2))
.isDelegated(false)
- .created(TestMessageId.of(2), TestMessageId.of(3), TestMessageId.of(4), TestMessageId.of(5))
+ .created(messageId2, messageId3, messageId4, messageId5)
.build();
EmailChange change2 = EmailChange.builder()
.accountId(ACCOUNT_ID)
- .state(State.of(UUID.randomUUID()))
+ .state(generateNewState())
.date(DATE.minusHours(1))
.isDelegated(false)
- .created(TestMessageId.of(6), TestMessageId.of(7))
- .updated(TestMessageId.of(2), TestMessageId.of(3), TestMessageId.of(10))
- .destroyed(TestMessageId.of(4), TestMessageId.of(9))
+ .created(messageId6, messageId7)
+ .updated(messageId2, messageId3, messageId10)
+ .destroyed(messageId4, messageId9)
.build();
EmailChange change3 = EmailChange.builder()
.accountId(ACCOUNT_ID)
- .state(State.of(UUID.randomUUID()))
+ .state(generateNewState())
.date(DATE)
.isDelegated(false)
- .created(TestMessageId.of(8))
- .updated(TestMessageId.of(6), TestMessageId.of(7), TestMessageId.of(1))
- .destroyed(TestMessageId.of(5), TestMessageId.of(10))
+ .created(messageId8)
+ .updated(messageId6, messageId7, messageId1)
+ .destroyed(messageId5, messageId10)
.build();
repository.save(oldState).block();
repository.save(change1).block();
repository.save(change2).block();
repository.save(change3).block();
- EmailChanges emailChanges = repository.getSinceState(ACCOUNT_ID, STATE_0, Optional.of(Limit.of(20))).block();
+ EmailChanges emailChanges = repository.getSinceState(ACCOUNT_ID, state, Optional.of(Limit.of(20))).block();
SoftAssertions.assertSoftly(softly -> {
- softly.assertThat(emailChanges.getCreated()).containsExactlyInAnyOrder(TestMessageId.of(2), TestMessageId.of(3), TestMessageId.of(6), TestMessageId.of(7), TestMessageId.of(8));
- softly.assertThat(emailChanges.getUpdated()).containsExactlyInAnyOrder(TestMessageId.of(1));
- softly.assertThat(emailChanges.getDestroyed()).containsExactlyInAnyOrder(TestMessageId.of(9), TestMessageId.of(10));
+ softly.assertThat(emailChanges.getCreated()).containsExactlyInAnyOrder(messageId2, messageId3, messageId6, messageId7, messageId8);
+ softly.assertThat(emailChanges.getUpdated()).containsExactlyInAnyOrder(messageId1);
+ softly.assertThat(emailChanges.getDestroyed()).containsExactlyInAnyOrder(messageId9, messageId10);
});
}
@@ -576,80 +668,96 @@ public interface EmailChangeRepositoryContract {
default void changesShouldNotReturnDelegatedChanges() {
EmailChangeRepository repository = emailChangeRepository();
+ State state = generateNewState();
+
+ MessageId messageId1 = generateNewMessageId();
+ MessageId messageId2 = generateNewMessageId();
+ MessageId messageId3 = generateNewMessageId();
+ MessageId messageId4 = generateNewMessageId();
+ MessageId messageId5 = generateNewMessageId();
+ MessageId messageId6 = generateNewMessageId();
+ MessageId messageId7 = generateNewMessageId();
+ MessageId messageId8 = generateNewMessageId();
EmailChange oldState = EmailChange.builder()
.accountId(ACCOUNT_ID)
- .state(STATE_0)
+ .state(state)
.date(DATE.minusHours(3))
.isDelegated(false)
- .created(TestMessageId.of(1))
+ .created(messageId1)
.build();
EmailChange change1 = EmailChange.builder()
.accountId(ACCOUNT_ID)
- .state(State.of(UUID.randomUUID()))
+ .state(generateNewState())
.date(DATE.minusHours(2))
.isDelegated(false)
- .created(TestMessageId.of(2), TestMessageId.of(3), TestMessageId.of(4), TestMessageId.of(5))
+ .created(messageId2, messageId3, messageId4, messageId5)
.build();
EmailChange change2 = EmailChange.builder()
.accountId(ACCOUNT_ID)
- .state(State.of(UUID.randomUUID()))
+ .state(generateNewState())
.date(DATE.minusHours(1))
.isDelegated(true)
- .created(TestMessageId.of(6), TestMessageId.of(7))
+ .created(messageId6, messageId7)
.build();
EmailChange change3 = EmailChange.builder()
.accountId(ACCOUNT_ID)
- .state(State.of(UUID.randomUUID()))
+ .state(generateNewState())
.date(DATE)
.isDelegated(false)
- .created(TestMessageId.of(8))
+ .created(messageId8)
.build();
repository.save(oldState).block();
repository.save(change1).block();
repository.save(change2).block();
repository.save(change3).block();
- EmailChanges emailChanges = repository.getSinceState(ACCOUNT_ID, STATE_0, Optional.of(Limit.of(20))).block();
+ EmailChanges emailChanges = repository.getSinceState(ACCOUNT_ID, state, Optional.of(Limit.of(20))).block();
assertThat(emailChanges.getCreated())
- .containsExactlyInAnyOrder(TestMessageId.of(2), TestMessageId.of(3), TestMessageId.of(4), TestMessageId.of(5), TestMessageId.of(8));
+ .containsExactlyInAnyOrder(messageId2, messageId3, messageId4, messageId5, messageId8);
}
@Test
default void getChangesShouldIgnoreDuplicatedValues() {
EmailChangeRepository repository = emailChangeRepository();
+ State state = generateNewState();
+
+ MessageId messageId1 = generateNewMessageId();
+ MessageId messageId2 = generateNewMessageId();
+ MessageId messageId3 = generateNewMessageId();
+
EmailChange oldState = EmailChange.builder()
.accountId(ACCOUNT_ID)
- .state(STATE_0)
+ .state(state)
.date(DATE.minusHours(2))
.isDelegated(false)
- .created(TestMessageId.of(1))
+ .created(messageId1)
.build();
EmailChange change1 = EmailChange.builder()
.accountId(ACCOUNT_ID)
- .state(State.of(UUID.randomUUID()))
+ .state(generateNewState())
.date(DATE.minusHours(1))
.isDelegated(false)
- .updated(TestMessageId.of(1), TestMessageId.of(2))
+ .updated(messageId1, messageId2)
.build();
EmailChange change2 = EmailChange.builder()
.accountId(ACCOUNT_ID)
- .state(State.of(UUID.randomUUID()))
+ .state(generateNewState())
.date(DATE)
.isDelegated(false)
- .updated(TestMessageId.of(1), TestMessageId.of(2))
- .created(TestMessageId.of(3))
+ .updated(messageId1, messageId2)
+ .created(messageId3)
.build();
repository.save(oldState).block();
repository.save(change1).block();
repository.save(change2).block();
- EmailChanges emailChanges = repository.getSinceState(ACCOUNT_ID, STATE_0, Optional.of(Limit.of(3))).block();
+ EmailChanges emailChanges = repository.getSinceState(ACCOUNT_ID, state, Optional.of(Limit.of(3))).block();
SoftAssertions.assertSoftly(softly -> {
- softly.assertThat(emailChanges.getUpdated()).containsExactly(TestMessageId.of(1), TestMessageId.of(2));
- softly.assertThat(emailChanges.getCreated()).containsExactly(TestMessageId.of(3));
+ softly.assertThat(emailChanges.getUpdated()).containsExactly(messageId1, messageId2);
+ softly.assertThat(emailChanges.getCreated()).containsExactly(messageId3);
});
}
@@ -657,7 +765,7 @@ public interface EmailChangeRepositoryContract {
default void getChangesShouldFailWhenSinceStateNotFound() {
EmailChangeRepository repository = emailChangeRepository();
- assertThatThrownBy(() -> repository.getSinceState(ACCOUNT_ID, STATE_0, Optional.empty()).block())
+ assertThatThrownBy(() -> repository.getSinceState(ACCOUNT_ID, generateNewState(), Optional.empty()).block())
.isInstanceOf(ChangeNotFoundException.class);
}
@@ -675,24 +783,24 @@ public interface EmailChangeRepositoryContract {
EmailChange change1 = EmailChange.builder()
.accountId(ACCOUNT_ID)
- .state(State.of(UUID.randomUUID()))
+ .state(generateNewState())
.date(DATE.minusHours(2))
.isDelegated(false)
- .created(TestMessageId.of(2))
+ .created(generateNewMessageId())
.build();
EmailChange change2 = EmailChange.builder()
.accountId(ACCOUNT_ID)
- .state(State.of(UUID.randomUUID()))
+ .state(generateNewState())
.date(DATE.minusHours(1))
.isDelegated(false)
- .created(TestMessageId.of(3))
+ .created(generateNewMessageId())
.build();
EmailChange change3 = EmailChange.builder()
.accountId(ACCOUNT_ID)
- .state(State.of(UUID.randomUUID()))
+ .state(generateNewState())
.date(DATE)
.isDelegated(false)
- .created(TestMessageId.of(4))
+ .created(generateNewMessageId())
.build();
repository.save(change1).block();
repository.save(change2).block();
@@ -708,24 +816,24 @@ public interface EmailChangeRepositoryContract {
EmailChange change1 = EmailChange.builder()
.accountId(ACCOUNT_ID)
- .state(State.of(UUID.randomUUID()))
+ .state(generateNewState())
.date(DATE.minusHours(2))
.isDelegated(false)
- .created(TestMessageId.of(2))
+ .created(generateNewMessageId())
.build();
EmailChange change2 = EmailChange.builder()
.accountId(ACCOUNT_ID)
- .state(State.of(UUID.randomUUID()))
+ .state(generateNewState())
.date(DATE.minusHours(1))
.isDelegated(false)
- .created(TestMessageId.of(3))
+ .created(generateNewMessageId())
.build();
EmailChange change3 = EmailChange.builder()
.accountId(ACCOUNT_ID)
- .state(State.of(UUID.randomUUID()))
+ .state(generateNewState())
.date(DATE)
.isDelegated(true)
- .created(TestMessageId.of(4))
+ .created(generateNewMessageId())
.build();
repository.save(change1).block();
repository.save(change2).block();
@@ -739,24 +847,26 @@ public interface EmailChangeRepositoryContract {
default void getSinceStateWithDelegationShouldSuccess() {
EmailChangeRepository repository = emailChangeRepository();
+ State state = generateNewState();
+
EmailChange oldState = EmailChange.builder()
.accountId(ACCOUNT_ID)
- .state(STATE_0)
+ .state(state)
.date(DATE.minusHours(1))
.isDelegated(false)
- .created(TestMessageId.of(1))
+ .created(generateNewMessageId())
.build();
EmailChange change = EmailChange.builder()
.accountId(ACCOUNT_ID)
- .state(State.of(UUID.randomUUID()))
+ .state(generateNewState())
.date(DATE)
.isDelegated(false)
- .updated(TestMessageId.of(1))
+ .updated(generateNewMessageId())
.build();
repository.save(oldState).block();
repository.save(change).block();
- assertThat(repository.getSinceStateWithDelegation(ACCOUNT_ID, STATE_0, Optional.empty()).block().getAllChanges())
+ assertThat(repository.getSinceStateWithDelegation(ACCOUNT_ID, state, Optional.empty()).block().getAllChanges())
.hasSameElementsAs(change.getUpdated());
}
@@ -764,16 +874,18 @@ public interface EmailChangeRepositoryContract {
default void getSinceStateWithDelegationShouldReturnEmptyWhenNoNewerState() {
EmailChangeRepository repository = emailChangeRepository();
+ State state = generateNewState();
+
EmailChange oldState = EmailChange.builder()
.accountId(ACCOUNT_ID)
- .state(STATE_0)
+ .state(state)
.date(DATE.minusHours(1))
.isDelegated(false)
- .created(TestMessageId.of(1))
+ .created(generateNewMessageId())
.build();
repository.save(oldState).block();
- assertThat(repository.getSinceStateWithDelegation(ACCOUNT_ID, STATE_0, Optional.empty()).block().getAllChanges())
+ assertThat(repository.getSinceStateWithDelegation(ACCOUNT_ID, state, Optional.empty()).block().getAllChanges())
.isEmpty();
}
@@ -781,16 +893,18 @@ public interface EmailChangeRepositoryContract {
default void getSinceStateWithDelegationShouldReturnCurrentStateWhenNoNewerState() {
EmailChangeRepository repository = emailChangeRepository();
+ State state = generateNewState();
+
EmailChange oldState = EmailChange.builder()
.accountId(ACCOUNT_ID)
- .state(STATE_0)
+ .state(state)
.date(DATE.minusHours(1))
.isDelegated(false)
- .created(TestMessageId.of(1))
+ .created(generateNewMessageId())
.build();
repository.save(oldState).block();
- assertThat(repository.getSinceStateWithDelegation(ACCOUNT_ID, STATE_0, Optional.empty()).block().getNewState())
+ assertThat(repository.getSinceStateWithDelegation(ACCOUNT_ID, state, Optional.empty()).block().getNewState())
.isEqualTo(oldState.getState());
}
@@ -798,40 +912,48 @@ public interface EmailChangeRepositoryContract {
default void getSinceStateWithDelegationShouldLimitChanges() {
EmailChangeRepository repository = emailChangeRepository();
+ State state = generateNewState();
+
+ MessageId messageId1 = generateNewMessageId();
+ MessageId messageId2 = generateNewMessageId();
+ MessageId messageId3 = generateNewMessageId();
+ MessageId messageId4 = generateNewMessageId();
+ MessageId messageId5 = generateNewMessageId();
+
EmailChange oldState = EmailChange.builder()
.accountId(ACCOUNT_ID)
- .state(STATE_0)
+ .state(state)
.date(DATE.minusHours(3))
.isDelegated(false)
- .created(TestMessageId.of(1))
+ .created(messageId1)
.build();
EmailChange change1 = EmailChange.builder()
.accountId(ACCOUNT_ID)
- .state(State.of(UUID.randomUUID()))
+ .state(generateNewState())
.date(DATE.minusHours(2))
.isDelegated(false)
- .created(TestMessageId.of(2))
+ .created(messageId2)
.build();
EmailChange change2 = EmailChange.builder()
.accountId(ACCOUNT_ID)
- .state(State.of(UUID.randomUUID()))
+ .state(generateNewState())
.date(DATE.minusHours(1))
.isDelegated(false)
- .created(TestMessageId.of(3))
+ .created(messageId3)
.build();
EmailChange change3 = EmailChange.builder()
.accountId(ACCOUNT_ID)
- .state(State.of(UUID.randomUUID()))
+ .state(generateNewState())
.date(DATE)
.isDelegated(false)
- .created(TestMessageId.of(4))
+ .created(messageId4)
.build();
EmailChange change4 = EmailChange.builder()
.accountId(ACCOUNT_ID)
- .state(State.of(UUID.randomUUID()))
+ .state(generateNewState())
.date(DATE.plusHours(1))
.isDelegated(false)
- .created(TestMessageId.of(5))
+ .created(messageId5)
.build();
repository.save(oldState).block();
repository.save(change1).block();
@@ -839,41 +961,46 @@ public interface EmailChangeRepositoryContract {
repository.save(change3).block();
repository.save(change4).block();
- assertThat(repository.getSinceStateWithDelegation(ACCOUNT_ID, STATE_0, Optional.of(Limit.of(3))).block().getCreated())
- .containsExactlyInAnyOrder(TestMessageId.of(2), TestMessageId.of(3), TestMessageId.of(4));
+ assertThat(repository.getSinceStateWithDelegation(ACCOUNT_ID, state, Optional.of(Limit.of(3))).block().getCreated())
+ .containsExactlyInAnyOrder(messageId2, messageId3, messageId4);
}
@Test
default void getSinceStateWithDelegationShouldReturnAllFromInitial() {
EmailChangeRepository repository = emailChangeRepository();
+ MessageId messageId1 = generateNewMessageId();
+ MessageId messageId2 = generateNewMessageId();
+ MessageId messageId3 = generateNewMessageId();
+ MessageId messageId4 = generateNewMessageId();
+
EmailChange oldState = EmailChange.builder()
.accountId(ACCOUNT_ID)
- .state(STATE_0)
+ .state(generateNewState())
.date(DATE.minusHours(3))
.isDelegated(false)
- .created(TestMessageId.of(1))
+ .created(messageId1)
.build();
EmailChange change1 = EmailChange.builder()
.accountId(ACCOUNT_ID)
- .state(State.of(UUID.randomUUID()))
+ .state(generateNewState())
.date(DATE.minusHours(2))
.isDelegated(false)
- .created(TestMessageId.of(2))
+ .created(messageId2)
.build();
EmailChange change2 = EmailChange.builder()
.accountId(ACCOUNT_ID)
- .state(State.of(UUID.randomUUID()))
+ .state(generateNewState())
.date(DATE.minusHours(1))
.isDelegated(false)
- .created(TestMessageId.of(3))
+ .created(messageId3)
.build();
EmailChange change3 = EmailChange.builder()
.accountId(ACCOUNT_ID)
- .state(State.of(UUID.randomUUID()))
+ .state(generateNewState())
.date(DATE)
.isDelegated(false)
- .created(TestMessageId.of(4))
+ .created(messageId4)
.build();
repository.save(oldState).block();
repository.save(change1).block();
@@ -881,40 +1008,42 @@ public interface EmailChangeRepositoryContract {
repository.save(change3).block();
assertThat(repository.getSinceStateWithDelegation(ACCOUNT_ID, State.INITIAL, Optional.of(Limit.of(3))).block().getCreated())
- .containsExactlyInAnyOrder(TestMessageId.of(1), TestMessageId.of(2), TestMessageId.of(3));
+ .containsExactlyInAnyOrder(messageId1, messageId2, messageId3);
}
@Test
default void getSinceStateWithDelegationShouldLimitChangesWhenMaxChangesOmitted() {
EmailChangeRepository repository = emailChangeRepository();
+ State state = generateNewState();
+
EmailChange oldState = EmailChange.builder()
.accountId(ACCOUNT_ID)
- .state(STATE_0)
+ .state(state)
.date(DATE.minusHours(2))
.isDelegated(false)
- .created(TestMessageId.of(1))
+ .created(generateNewMessageId())
.build();
EmailChange change1 = EmailChange.builder()
.accountId(ACCOUNT_ID)
- .state(State.of(UUID.randomUUID()))
+ .state(generateNewState())
.date(DATE.minusHours(1))
.isDelegated(false)
- .created(TestMessageId.of(2), TestMessageId.of(3), TestMessageId.of(4), TestMessageId.of(5), TestMessageId.of(6))
+ .created(generateNewMessageId(), generateNewMessageId(), generateNewMessageId(), generateNewMessageId(), generateNewMessageId())
.build();
EmailChange change2 = EmailChange.builder()
.accountId(ACCOUNT_ID)
- .state(State.of(UUID.randomUUID()))
+ .state(generateNewState())
.date(DATE)
.isDelegated(false)
- .created(TestMessageId.of(7))
+ .created(generateNewMessageId())
.build();
repository.save(oldState).block();
repository.save(change1).block();
repository.save(change2).block();
- assertThat(repository.getSinceStateWithDelegation(ACCOUNT_ID, STATE_0, Optional.empty()).block().getAllChanges())
+ assertThat(repository.getSinceStateWithDelegation(ACCOUNT_ID, state, Optional.empty()).block().getAllChanges())
.hasSameElementsAs(change1.getCreated());
}
@@ -922,32 +1051,34 @@ public interface EmailChangeRepositoryContract {
default void getSinceStateWithDelegationShouldNotReturnMoreThanMaxChanges() {
EmailChangeRepository repository = emailChangeRepository();
+ State state = generateNewState();
+
EmailChange oldState = EmailChange.builder()
.accountId(ACCOUNT_ID)
- .state(STATE_0)
+ .state(state)
.date(DATE.minusHours(2))
.isDelegated(false)
- .created(TestMessageId.of(1))
+ .created(generateNewMessageId())
.build();
EmailChange change1 = EmailChange.builder()
.accountId(ACCOUNT_ID)
- .state(State.of(UUID.randomUUID()))
+ .state(generateNewState())
.date(DATE.minusHours(1))
.isDelegated(false)
- .created(TestMessageId.of(2), TestMessageId.of(3))
+ .created(generateNewMessageId(), generateNewMessageId())
.build();
EmailChange change2 = EmailChange.builder()
.accountId(ACCOUNT_ID)
- .state(State.of(UUID.randomUUID()))
+ .state(generateNewState())
.date(DATE)
.isDelegated(false)
- .created(TestMessageId.of(4), TestMessageId.of(5))
+ .created(generateNewMessageId(), generateNewMessageId())
.build();
repository.save(oldState).block();
repository.save(change1).block();
repository.save(change2).block();
- assertThat(repository.getSinceStateWithDelegation(ACCOUNT_ID, STATE_0, Optional.of(Limit.of(3))).block().getAllChanges())
+ assertThat(repository.getSinceStateWithDelegation(ACCOUNT_ID, state, Optional.of(Limit.of(3))).block().getAllChanges())
.hasSameElementsAs(change1.getCreated());
}
@@ -955,31 +1086,33 @@ public interface EmailChangeRepositoryContract {
default void getSinceStateWithDelegationShouldReturnEmptyWhenNumberOfChangesExceedMaxChanges() {
EmailChangeRepository repository = emailChangeRepository();
+ State state = generateNewState();
+
EmailChange oldState = EmailChange.builder()
.accountId(ACCOUNT_ID)
- .state(STATE_0)
+ .state(state)
.date(DATE.minusHours(2))
.isDelegated(false)
- .created(TestMessageId.of(1))
+ .created(generateNewMessageId())
.build();
EmailChange change1 = EmailChange.builder()
.accountId(ACCOUNT_ID)
- .state(State.of(UUID.randomUUID()))
+ .state(generateNewState())
.date(DATE.minusHours(1))
.isDelegated(false)
- .created(TestMessageId.of(2), TestMessageId.of(3))
+ .created(generateNewMessageId(), generateNewMessageId())
.build();
EmailChange change2 = EmailChange.builder()
.accountId(ACCOUNT_ID)
- .state(State.of(UUID.randomUUID()))
+ .state(generateNewState())
.date(DATE)
.isDelegated(false)
- .created(TestMessageId.of(4), TestMessageId.of(5))
+ .created(generateNewMessageId(), generateNewMessageId())
.build();
repository.save(oldState).block();
repository.save(change1).block();
- assertThat(repository.getSinceStateWithDelegation(ACCOUNT_ID, STATE_0, Optional.of(Limit.of(1))).block().getAllChanges())
+ assertThat(repository.getSinceStateWithDelegation(ACCOUNT_ID, state, Optional.of(Limit.of(1))).block().getAllChanges())
.isEmpty();
}
@@ -987,32 +1120,34 @@ public interface EmailChangeRepositoryContract {
default void getSinceStateWithDelegationShouldReturnNewState() {
EmailChangeRepository repository = emailChangeRepository();
+ State state = generateNewState();
+
EmailChange oldState = EmailChange.builder()
.accountId(ACCOUNT_ID)
- .state(STATE_0)
+ .state(state)
.date(DATE.minusHours(2))
.isDelegated(false)
- .created(TestMessageId.of(1))
+ .created(generateNewMessageId())
.build();
EmailChange change1 = EmailChange.builder()
.accountId(ACCOUNT_ID)
- .state(State.of(UUID.randomUUID()))
+ .state(generateNewState())
.date(DATE.minusHours(1))
.isDelegated(false)
- .created(TestMessageId.of(2), TestMessageId.of(3))
+ .created(generateNewMessageId(), generateNewMessageId())
.build();
EmailChange change2 = EmailChange.builder()
.accountId(ACCOUNT_ID)
- .state(State.of(UUID.randomUUID()))
+ .state(generateNewState())
.date(DATE)
.isDelegated(false)
- .updated(TestMessageId.of(2), TestMessageId.of(3))
+ .updated(generateNewMessageId(), generateNewMessageId())
.build();
repository.save(oldState).block();
repository.save(change1).block();
repository.save(change2).block();
- assertThat(repository.getSinceStateWithDelegation(ACCOUNT_ID, STATE_0, Optional.empty()).block().getNewState())
+ assertThat(repository.getSinceStateWithDelegation(ACCOUNT_ID, state, Optional.empty()).block().getNewState())
.isEqualTo(change2.getState());
}
@@ -1020,32 +1155,34 @@ public interface EmailChangeRepositoryContract {
default void getSinceStateWithDelegationHasMoreChangesShouldBeTrueWhenMoreChanges() {
EmailChangeRepository repository = emailChangeRepository();
+ State state = generateNewState();
+
EmailChange oldState = EmailChange.builder()
.accountId(ACCOUNT_ID)
- .state(STATE_0)
+ .state(state)
.date(DATE.minusHours(2))
.isDelegated(false)
- .created(TestMessageId.of(1))
+ .created(generateNewMessageId())
.build();
EmailChange change1 = EmailChange.builder()
.accountId(ACCOUNT_ID)
- .state(State.of(UUID.randomUUID()))
+ .state(generateNewState())
.date(DATE.minusHours(1))
.isDelegated(false)
- .created(TestMessageId.of(2), TestMessageId.of(3))
+ .created(generateNewMessageId(), generateNewMessageId())
.build();
EmailChange change2 = EmailChange.builder()
.accountId(ACCOUNT_ID)
- .state(State.of(UUID.randomUUID()))
+ .state(generateNewState())
.date(DATE)
.isDelegated(false)
- .updated(TestMessageId.of(2), TestMessageId.of(3))
+ .updated(generateNewMessageId(), generateNewMessageId())
.build();
repository.save(oldState).block();
repository.save(change1).block();
repository.save(change2).block();
- assertThat(repository.getSinceStateWithDelegation(ACCOUNT_ID, STATE_0, Optional.of(Limit.of(1))).block().hasMoreChanges())
+ assertThat(repository.getSinceStateWithDelegation(ACCOUNT_ID, state, Optional.of(Limit.of(1))).block().hasMoreChanges())
.isTrue();
}
@@ -1053,32 +1190,34 @@ public interface EmailChangeRepositoryContract {
default void getSinceStateWithDelegationHasMoreChangesShouldBeFalseWhenNoMoreChanges() {
EmailChangeRepository repository = emailChangeRepository();
+ State state = generateNewState();
+
EmailChange oldState = EmailChange.builder()
.accountId(ACCOUNT_ID)
- .state(STATE_0)
+ .state(state)
.date(DATE.minusHours(2))
.isDelegated(false)
- .created(TestMessageId.of(1))
+ .created(generateNewMessageId())
.build();
EmailChange change1 = EmailChange.builder()
.accountId(ACCOUNT_ID)
- .state(State.of(UUID.randomUUID()))
+ .state(generateNewState())
.date(DATE.minusHours(1))
.isDelegated(false)
- .created(TestMessageId.of(2), TestMessageId.of(3))
+ .created(generateNewMessageId(), generateNewMessageId())
.build();
EmailChange change2 = EmailChange.builder()
.accountId(ACCOUNT_ID)
- .state(State.of(UUID.randomUUID()))
+ .state(generateNewState())
.date(DATE)
.isDelegated(false)
- .updated(TestMessageId.of(2), TestMessageId.of(3))
+ .updated(generateNewMessageId(), generateNewMessageId())
.build();
repository.save(oldState).block();
repository.save(change1).block();
repository.save(change2).block();
- assertThat(repository.getSinceStateWithDelegation(ACCOUNT_ID, STATE_0, Optional.of(Limit.of(4))).block().hasMoreChanges())
+ assertThat(repository.getSinceStateWithDelegation(ACCOUNT_ID, state, Optional.of(Limit.of(4))).block().hasMoreChanges())
.isFalse();
}
@@ -1086,49 +1225,62 @@ public interface EmailChangeRepositoryContract {
default void getSinceStateWithDelegationShouldReturnChangesInTheirRespectiveType() {
EmailChangeRepository repository = emailChangeRepository();
+ State state = generateNewState();
+
+ MessageId messageId1 = generateNewMessageId();
+ MessageId messageId2 = generateNewMessageId();
+ MessageId messageId3 = generateNewMessageId();
+ MessageId messageId4 = generateNewMessageId();
+ MessageId messageId5 = generateNewMessageId();
+ MessageId messageId6 = generateNewMessageId();
+ MessageId messageId7 = generateNewMessageId();
+ MessageId messageId8 = generateNewMessageId();
+ MessageId messageId9 = generateNewMessageId();
+ MessageId messageId10 = generateNewMessageId();
+
EmailChange oldState = EmailChange.builder()
.accountId(ACCOUNT_ID)
- .state(STATE_0)
+ .state(state)
.date(DATE.minusHours(3))
.isDelegated(false)
- .created(TestMessageId.of(1), TestMessageId.of(9), TestMessageId.of(10))
+ .created(messageId1, messageId9, messageId10)
.build();
EmailChange change1 = EmailChange.builder()
.accountId(ACCOUNT_ID)
- .state(State.of(UUID.randomUUID()))
+ .state(generateNewState())
.date(DATE.minusHours(2))
.isDelegated(false)
- .created(TestMessageId.of(2), TestMessageId.of(3), TestMessageId.of(4), TestMessageId.of(5))
+ .created(messageId2, messageId3, messageId4, messageId5)
.build();
EmailChange change2 = EmailChange.builder()
.accountId(ACCOUNT_ID)
- .state(State.of(UUID.randomUUID()))
+ .state(generateNewState())
.date(DATE.minusHours(1))
.isDelegated(false)
- .created(TestMessageId.of(6), TestMessageId.of(7))
- .updated(TestMessageId.of(2), TestMessageId.of(3), TestMessageId.of(10))
- .destroyed(TestMessageId.of(4), TestMessageId.of(9))
+ .created(messageId6, messageId7)
+ .updated(messageId2, messageId3, messageId10)
+ .destroyed(messageId4, messageId9)
.build();
EmailChange change3 = EmailChange.builder()
.accountId(ACCOUNT_ID)
- .state(State.of(UUID.randomUUID()))
+ .state(generateNewState())
.date(DATE)
.isDelegated(false)
- .created(TestMessageId.of(8))
- .updated(TestMessageId.of(6), TestMessageId.of(7), TestMessageId.of(1))
- .destroyed(TestMessageId.of(5), TestMessageId.of(10))
+ .created(messageId8)
+ .updated(messageId6, messageId7, messageId1)
+ .destroyed(messageId5, messageId10)
.build();
repository.save(oldState).block();
repository.save(change1).block();
repository.save(change2).block();
repository.save(change3).block();
- EmailChanges emailChanges = repository.getSinceState(ACCOUNT_ID, STATE_0, Optional.of(Limit.of(20))).block();
+ EmailChanges emailChanges = repository.getSinceState(ACCOUNT_ID, state, Optional.of(Limit.of(20))).block();
SoftAssertions.assertSoftly(softly -> {
- softly.assertThat(emailChanges.getCreated()).containsExactlyInAnyOrder(TestMessageId.of(2), TestMessageId.of(3), TestMessageId.of(6), TestMessageId.of(7), TestMessageId.of(8));
- softly.assertThat(emailChanges.getUpdated()).containsExactlyInAnyOrder(TestMessageId.of(1));
- softly.assertThat(emailChanges.getDestroyed()).containsExactlyInAnyOrder(TestMessageId.of(9), TestMessageId.of(10));
+ softly.assertThat(emailChanges.getCreated()).containsExactlyInAnyOrder(messageId2, messageId3, messageId6, messageId7, messageId8);
+ softly.assertThat(emailChanges.getUpdated()).containsExactlyInAnyOrder(messageId1);
+ softly.assertThat(emailChanges.getDestroyed()).containsExactlyInAnyOrder(messageId9, messageId10);
});
}
@@ -1136,80 +1288,95 @@ public interface EmailChangeRepositoryContract {
default void getSinceStateWithDelegationShouldReturnDelegatedChanges() {
EmailChangeRepository repository = emailChangeRepository();
+ State state = generateNewState();
+ MessageId messageId1 = generateNewMessageId();
+ MessageId messageId2 = generateNewMessageId();
+ MessageId messageId3 = generateNewMessageId();
+ MessageId messageId4 = generateNewMessageId();
+ MessageId messageId5 = generateNewMessageId();
+ MessageId messageId6 = generateNewMessageId();
+ MessageId messageId7 = generateNewMessageId();
+ MessageId messageId8 = generateNewMessageId();
EmailChange oldState = EmailChange.builder()
.accountId(ACCOUNT_ID)
- .state(STATE_0)
+ .state(state)
.date(DATE.minusHours(3))
.isDelegated(false)
- .created(TestMessageId.of(1))
+ .created(messageId1)
.build();
EmailChange change1 = EmailChange.builder()
.accountId(ACCOUNT_ID)
- .state(State.of(UUID.randomUUID()))
+ .state(generateNewState())
.date(DATE.minusHours(2))
.isDelegated(false)
- .created(TestMessageId.of(2), TestMessageId.of(3), TestMessageId.of(4), TestMessageId.of(5))
+ .created(messageId2, messageId3, messageId4, messageId5)
.build();
EmailChange change2 = EmailChange.builder()
.accountId(ACCOUNT_ID)
- .state(State.of(UUID.randomUUID()))
+ .state(generateNewState())
.date(DATE.minusHours(1))
.isDelegated(true)
- .created(TestMessageId.of(6), TestMessageId.of(7))
+ .created(messageId6, messageId7)
.build();
EmailChange change3 = EmailChange.builder()
.accountId(ACCOUNT_ID)
- .state(State.of(UUID.randomUUID()))
+ .state(generateNewState())
.date(DATE)
.isDelegated(false)
- .created(TestMessageId.of(8))
+ .created(messageId8)
.build();
repository.save(oldState).block();
repository.save(change1).block();
repository.save(change2).block();
repository.save(change3).block();
- EmailChanges emailChanges = repository.getSinceStateWithDelegation(ACCOUNT_ID, STATE_0, Optional.of(Limit.of(20))).block();
+ EmailChanges emailChanges = repository.getSinceStateWithDelegation(ACCOUNT_ID, state, Optional.of(Limit.of(20))).block();
assertThat(emailChanges.getCreated())
- .containsExactlyInAnyOrder(TestMessageId.of(2), TestMessageId.of(3), TestMessageId.of(4), TestMessageId.of(5), TestMessageId.of(6), TestMessageId.of(7), TestMessageId.of(8));
+ .containsExactlyInAnyOrder(messageId2, messageId3, messageId4, messageId5, messageId6, messageId7, messageId8);
}
@Test
default void getSinceStateWithDelegationShouldIgnoreDuplicatedValues() {
EmailChangeRepository repository = emailChangeRepository();
+ State state = generateNewState();
+
+ MessageId messageId1 = generateNewMessageId();
+ MessageId messageId2 = generateNewMessageId();
+ MessageId messageId3 = generateNewMessageId();
+
EmailChange oldState = EmailChange.builder()
.accountId(ACCOUNT_ID)
- .state(STATE_0)
+ .state(state)
.date(DATE.minusHours(2))
.isDelegated(false)
- .created(TestMessageId.of(1))
+ .created(messageId1)
.build();
EmailChange change1 = EmailChange.builder()
.accountId(ACCOUNT_ID)
- .state(State.of(UUID.randomUUID()))
+ .state(generateNewState())
.date(DATE.minusHours(1))
.isDelegated(false)
- .updated(TestMessageId.of(1), TestMessageId.of(2))
+ .updated(messageId1, messageId2)
.build();
EmailChange change2 = EmailChange.builder()
.accountId(ACCOUNT_ID)
- .state(State.of(UUID.randomUUID()))
+ .state(generateNewState())
.date(DATE)
.isDelegated(false)
- .updated(TestMessageId.of(1), TestMessageId.of(2))
- .created(TestMessageId.of(3))
+ .updated(messageId1, messageId2)
+ .created(messageId3)
.build();
repository.save(oldState).block();
repository.save(change1).block();
repository.save(change2).block();
- EmailChanges emailChanges = repository.getSinceStateWithDelegation(ACCOUNT_ID, STATE_0, Optional.of(Limit.of(3))).block();
+ EmailChanges emailChanges = repository.getSinceStateWithDelegation(ACCOUNT_ID, state, Optional.of(Limit.of(3))).block();
SoftAssertions.assertSoftly(softly -> {
- softly.assertThat(emailChanges.getUpdated()).containsExactly(TestMessageId.of(1), TestMessageId.of(2));
- softly.assertThat(emailChanges.getCreated()).containsExactly(TestMessageId.of(3));
+ softly.assertThat(emailChanges.getUpdated()).containsExactly(messageId1, messageId2);
+ softly.assertThat(emailChanges.getCreated()).containsExactly(messageId3);
});
}
@@ -1217,7 +1384,7 @@ public interface EmailChangeRepositoryContract {
default void getSinceStateWithDelegationShouldFailWhenSinceStateNotFound() {
EmailChangeRepository repository = emailChangeRepository();
- assertThatThrownBy(() -> repository.getSinceStateWithDelegation(ACCOUNT_ID, STATE_0, Optional.empty()).block())
+ assertThatThrownBy(() -> repository.getSinceStateWithDelegation(ACCOUNT_ID, generateNewState(), Optional.empty()).block())
.isInstanceOf(ChangeNotFoundException.class);
}
}
diff --git a/server/data/data-jmap/src/test/java/org/apache/james/jmap/memory/change/MemoryEmailChangeRepositoryTest.java b/server/data/data-jmap/src/test/java/org/apache/james/jmap/memory/change/MemoryEmailChangeRepositoryTest.java
index 3b1abc1..f7711db 100644
--- a/server/data/data-jmap/src/test/java/org/apache/james/jmap/memory/change/MemoryEmailChangeRepositoryTest.java
+++ b/server/data/data-jmap/src/test/java/org/apache/james/jmap/memory/change/MemoryEmailChangeRepositoryTest.java
@@ -19,9 +19,13 @@
package org.apache.james.jmap.memory.change;
+import java.util.concurrent.ThreadLocalRandom;
+
import org.apache.james.jmap.api.change.EmailChangeRepository;
import org.apache.james.jmap.api.change.EmailChangeRepositoryContract;
-import org.apache.james.jmap.api.change.MailboxChangeRepository;
+import org.apache.james.jmap.api.change.State;
+import org.apache.james.mailbox.model.MessageId;
+import org.apache.james.mailbox.model.TestMessageId;
import org.junit.jupiter.api.BeforeEach;
public class MemoryEmailChangeRepositoryTest implements EmailChangeRepositoryContract {
@@ -36,4 +40,14 @@ public class MemoryEmailChangeRepositoryTest implements EmailChangeRepositoryCon
public EmailChangeRepository emailChangeRepository() {
return emailChangeRepository;
}
+
+ @Override
+ public State generateNewState() {
+ return State.Factory.DEFAULT.generate();
+ }
+
+ @Override
+ public MessageId generateNewMessageId() {
+ return TestMessageId.of(ThreadLocalRandom.current().nextLong());
+ }
}
---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscribe@james.apache.org
For additional commands, e-mail: notifications-help@james.apache.org
[james-project] 07/11: JAMES-3470 Binding for
CassandraEmailChangeModule
Posted by rc...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
rcordier pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/james-project.git
commit fcc9ef94faf59b9a4ee45376573e281002a7d897
Author: LanKhuat <dl...@linagora.com>
AuthorDate: Mon Jan 11 10:10:56 2021 +0700
JAMES-3470 Binding for CassandraEmailChangeModule
---
.../main/java/org/apache/james/modules/data/CassandraJmapModule.java | 2 ++
1 file changed, 2 insertions(+)
diff --git a/server/container/guice/cassandra-guice/src/main/java/org/apache/james/modules/data/CassandraJmapModule.java b/server/container/guice/cassandra-guice/src/main/java/org/apache/james/modules/data/CassandraJmapModule.java
index dfcfad8..1f64753 100644
--- a/server/container/guice/cassandra-guice/src/main/java/org/apache/james/modules/data/CassandraJmapModule.java
+++ b/server/container/guice/cassandra-guice/src/main/java/org/apache/james/modules/data/CassandraJmapModule.java
@@ -34,6 +34,7 @@ import org.apache.james.jmap.api.vacation.NotificationRegistry;
import org.apache.james.jmap.api.vacation.VacationRepository;
import org.apache.james.jmap.cassandra.access.CassandraAccessModule;
import org.apache.james.jmap.cassandra.access.CassandraAccessTokenRepository;
+import org.apache.james.jmap.cassandra.change.CassandraEmailChangeModule;
import org.apache.james.jmap.cassandra.change.CassandraMailboxChangeModule;
import org.apache.james.jmap.cassandra.filtering.FilteringRuleSetDefineDTOModules;
import org.apache.james.jmap.cassandra.projections.CassandraEmailQueryView;
@@ -83,6 +84,7 @@ public class CassandraJmapModule extends AbstractModule {
cassandraDataDefinitions.addBinding().toInstance(CassandraMessageFastViewProjectionModule.MODULE);
cassandraDataDefinitions.addBinding().toInstance(CassandraEmailQueryViewModule.MODULE);
cassandraDataDefinitions.addBinding().toInstance(CassandraMailboxChangeModule.MODULE);
+ cassandraDataDefinitions.addBinding().toInstance(CassandraEmailChangeModule.MODULE);
Multibinder<EventDTOModule<? extends Event, ? extends EventDTO>> eventDTOModuleBinder = Multibinder.newSetBinder(binder(), new TypeLiteral<EventDTOModule<? extends Event, ? extends EventDTO>>() {});
eventDTOModuleBinder.addBinding().toInstance(FilteringRuleSetDefineDTOModules.FILTERING_RULE_SET_DEFINED);
---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscribe@james.apache.org
For additional commands, e-mail: notifications-help@james.apache.org