JAMES-2541 Add tests for JSON structure stability
Project: http://git-wip-us.apache.org/repos/asf/james-project/repo Commit: http://git-wip-us.apache.org/repos/asf/james-project/commit/f6f9961a Tree: http://git-wip-us.apache.org/repos/asf/james-project/tree/f6f9961a Diff: http://git-wip-us.apache.org/repos/asf/james-project/diff/f6f9961a Branch: refs/heads/master Commit: f6f9961ac053ed245b1d362e6747e6bdba4ee8dc Parents: 7dc41ae Author: Benoit Tellier <[email protected]> Authored: Fri Sep 7 17:02:27 2018 +0700 Committer: Benoit Tellier <[email protected]> Committed: Mon Sep 10 17:19:38 2018 +0700 ---------------------------------------------------------------------- server/queue/queue-rabbitmq/pom.xml | 5 + .../apache/james/queue/rabbitmq/HeadersDto.java | 20 ++- .../apache/james/queue/rabbitmq/MailDTO.java | 50 ++++++-- .../james/queue/rabbitmq/RabbitMQMailQueue.java | 8 +- .../james/queue/rabbitmq/MailDTOTest.java | 122 +++++++++++++++++++ .../src/test/resources/json/mail1.json | 16 +++ .../src/test/resources/json/mail_min.json | 14 +++ 7 files changed, 221 insertions(+), 14 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/james-project/blob/f6f9961a/server/queue/queue-rabbitmq/pom.xml ---------------------------------------------------------------------- diff --git a/server/queue/queue-rabbitmq/pom.xml b/server/queue/queue-rabbitmq/pom.xml index 1dc37ef..2884684 100644 --- a/server/queue/queue-rabbitmq/pom.xml +++ b/server/queue/queue-rabbitmq/pom.xml @@ -140,6 +140,11 @@ <artifactId>javax.inject</artifactId> </dependency> <dependency> + <groupId>net.javacrumbs.json-unit</groupId> + <artifactId>json-unit-assertj</artifactId> + <scope>test</scope> + </dependency> + <dependency> <groupId>nl.jqno.equalsverifier</groupId> <artifactId>equalsverifier</artifactId> <scope>test</scope> http://git-wip-us.apache.org/repos/asf/james-project/blob/f6f9961a/server/queue/queue-rabbitmq/src/main/java/org/apache/james/queue/rabbitmq/HeadersDto.java ---------------------------------------------------------------------- diff --git a/server/queue/queue-rabbitmq/src/main/java/org/apache/james/queue/rabbitmq/HeadersDto.java b/server/queue/queue-rabbitmq/src/main/java/org/apache/james/queue/rabbitmq/HeadersDto.java index 5d6061b..e2ed6c6 100644 --- a/server/queue/queue-rabbitmq/src/main/java/org/apache/james/queue/rabbitmq/HeadersDto.java +++ b/server/queue/queue-rabbitmq/src/main/java/org/apache/james/queue/rabbitmq/HeadersDto.java @@ -20,6 +20,7 @@ package org.apache.james.queue.rabbitmq; import java.util.Collection; +import java.util.Objects; import org.apache.mailet.PerRecipientHeaders; @@ -31,7 +32,7 @@ import com.google.common.collect.Multimap; public class HeadersDto { - public static HeadersDto from(Collection<PerRecipientHeaders.Header> headers) { + static HeadersDto from(Collection<PerRecipientHeaders.Header> headers) { return new HeadersDto(headers.stream() .collect(ImmutableListMultimap.toImmutableListMultimap( PerRecipientHeaders.Header::getName, @@ -50,7 +51,7 @@ public class HeadersDto { return headers; } - public Collection<PerRecipientHeaders.Header> toHeaders() { + Collection<PerRecipientHeaders.Header> toHeaders() { return headers.entries() .stream() .map(entry -> PerRecipientHeaders.Header.builder() @@ -59,4 +60,19 @@ public class HeadersDto { .build()) .collect(ImmutableList.toImmutableList()); } + + @Override + public final boolean equals(Object o) { + if (o instanceof HeadersDto) { + HeadersDto that = (HeadersDto) o; + + return Objects.equals(this.headers, that.headers); + } + return false; + } + + @Override + public final int hashCode() { + return Objects.hash(headers); + } } http://git-wip-us.apache.org/repos/asf/james-project/blob/f6f9961a/server/queue/queue-rabbitmq/src/main/java/org/apache/james/queue/rabbitmq/MailDTO.java ---------------------------------------------------------------------- diff --git a/server/queue/queue-rabbitmq/src/main/java/org/apache/james/queue/rabbitmq/MailDTO.java b/server/queue/queue-rabbitmq/src/main/java/org/apache/james/queue/rabbitmq/MailDTO.java index d760f18..c4b9d28 100644 --- a/server/queue/queue-rabbitmq/src/main/java/org/apache/james/queue/rabbitmq/MailDTO.java +++ b/server/queue/queue-rabbitmq/src/main/java/org/apache/james/queue/rabbitmq/MailDTO.java @@ -21,9 +21,12 @@ package org.apache.james.queue.rabbitmq; import java.time.Instant; import java.util.Collection; +import java.util.Date; import java.util.Map; +import java.util.Objects; +import java.util.Optional; +import java.util.stream.Stream; -import org.apache.commons.lang3.tuple.Pair; import org.apache.james.blob.mail.MimeMessagePartsId; import org.apache.james.core.MailAddress; import org.apache.james.util.SerializationUtil; @@ -41,14 +44,15 @@ class MailDTO { static MailDTO fromMail(Mail mail, MimeMessagePartsId partsId) { return new MailDTO( - mail.getRecipients().stream() + Optional.ofNullable(mail.getRecipients()).map(Collection::stream) + .orElse(Stream.empty()) .map(MailAddress::asString) .collect(Guavate.toImmutableList()), mail.getName(), - mail.getSender().asString(), + Optional.ofNullable(mail.getSender()).map(MailAddress::asString), mail.getState(), mail.getErrorMessage(), - mail.getLastUpdated().toInstant(), + Optional.ofNullable(mail.getLastUpdated()).map(Date::toInstant), serializedAttributes(mail), mail.getRemoteAddr(), mail.getRemoteHost(), @@ -76,10 +80,10 @@ class MailDTO { private final ImmutableList<String> recipients; private final String name; - private final String sender; + private final Optional<String> sender; private final String state; private final String errorMessage; - private final Instant lastUpdated; + private final Optional<Instant> lastUpdated; private final ImmutableMap<String, String> attributes; private final String remoteAddr; private final String remoteHost; @@ -90,10 +94,10 @@ class MailDTO { @JsonCreator private MailDTO(@JsonProperty("recipients") ImmutableList<String> recipients, @JsonProperty("name") String name, - @JsonProperty("sender") String sender, + @JsonProperty("sender") Optional<String> sender, @JsonProperty("state") String state, @JsonProperty("errorMessage") String errorMessage, - @JsonProperty("lastUpdated") Instant lastUpdated, + @JsonProperty("lastUpdated") Optional<Instant> lastUpdated, @JsonProperty("attributes") ImmutableMap<String, String> attributes, @JsonProperty("remoteAddr") String remoteAddr, @JsonProperty("remoteHost") String remoteHost, @@ -125,7 +129,7 @@ class MailDTO { } @JsonProperty("sender") - String getSender() { + Optional<String> getSender() { return sender; } @@ -140,7 +144,7 @@ class MailDTO { } @JsonProperty("lastUpdated") - Instant getLastUpdated() { + Optional<Instant> getLastUpdated() { return lastUpdated; } @@ -173,4 +177,30 @@ class MailDTO { String getBodyBlobId() { return bodyBlobId; } + + @Override + public final boolean equals(Object o) { + if (o instanceof MailDTO) { + MailDTO mailDTO = (MailDTO) o; + + return Objects.equals(this.recipients, mailDTO.recipients) + && Objects.equals(this.name, mailDTO.name) + && Objects.equals(this.sender, mailDTO.sender) + && Objects.equals(this.state, mailDTO.state) + && Objects.equals(this.errorMessage, mailDTO.errorMessage) + && Objects.equals(this.lastUpdated, mailDTO.lastUpdated) + && Objects.equals(this.attributes, mailDTO.attributes) + && Objects.equals(this.remoteAddr, mailDTO.remoteAddr) + && Objects.equals(this.remoteHost, mailDTO.remoteHost) + && Objects.equals(this.perRecipientHeaders, mailDTO.perRecipientHeaders) + && Objects.equals(this.headerBlobId, mailDTO.headerBlobId) + && Objects.equals(this.bodyBlobId, mailDTO.bodyBlobId); + } + return false; + } + + @Override + public final int hashCode() { + return Objects.hash(recipients, name, sender, state, errorMessage, lastUpdated, attributes, remoteAddr, remoteHost, perRecipientHeaders, headerBlobId, bodyBlobId); + } } http://git-wip-us.apache.org/repos/asf/james-project/blob/f6f9961a/server/queue/queue-rabbitmq/src/main/java/org/apache/james/queue/rabbitmq/RabbitMQMailQueue.java ---------------------------------------------------------------------- diff --git a/server/queue/queue-rabbitmq/src/main/java/org/apache/james/queue/rabbitmq/RabbitMQMailQueue.java b/server/queue/queue-rabbitmq/src/main/java/org/apache/james/queue/rabbitmq/RabbitMQMailQueue.java index 10300cd..f9ad07c 100644 --- a/server/queue/queue-rabbitmq/src/main/java/org/apache/james/queue/rabbitmq/RabbitMQMailQueue.java +++ b/server/queue/queue-rabbitmq/src/main/java/org/apache/james/queue/rabbitmq/RabbitMQMailQueue.java @@ -21,6 +21,7 @@ package org.apache.james.queue.rabbitmq; import java.io.IOException; import java.io.Serializable; +import java.time.Instant; import java.util.Date; import java.util.concurrent.CompletableFuture; import java.util.concurrent.Executors; @@ -203,7 +204,7 @@ public class RabbitMQMailQueue implements MailQueue { MailImpl mail = new MailImpl( dto.getName(), - MailAddress.getMailSender(dto.getSender()), + dto.getSender().map(MailAddress::getMailSender).orElse(null), dto.getRecipients() .stream() .map(Throwing.<String, MailAddress>function(MailAddress::new).sneakyThrow()) @@ -214,7 +215,10 @@ public class RabbitMQMailQueue implements MailQueue { mail.setRemoteAddr(dto.getRemoteAddr()); mail.setRemoteHost(dto.getRemoteHost()); mail.setState(dto.getState()); - mail.setLastUpdated(new Date(dto.getLastUpdated().toEpochMilli())); + dto.getLastUpdated() + .map(Instant::toEpochMilli) + .map(Date::new) + .ifPresent(mail::setLastUpdated); dto.getAttributes() .forEach((name, value) -> mail.setAttribute(name, SerializationUtil.<Serializable>deserialize(value))); http://git-wip-us.apache.org/repos/asf/james-project/blob/f6f9961a/server/queue/queue-rabbitmq/src/test/java/org/apache/james/queue/rabbitmq/MailDTOTest.java ---------------------------------------------------------------------- diff --git a/server/queue/queue-rabbitmq/src/test/java/org/apache/james/queue/rabbitmq/MailDTOTest.java b/server/queue/queue-rabbitmq/src/test/java/org/apache/james/queue/rabbitmq/MailDTOTest.java new file mode 100644 index 0000000..695e978 --- /dev/null +++ b/server/queue/queue-rabbitmq/src/test/java/org/apache/james/queue/rabbitmq/MailDTOTest.java @@ -0,0 +1,122 @@ +/**************************************************************** + * 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.queue.rabbitmq; + +import static net.javacrumbs.jsonunit.assertj.JsonAssertions.assertThatJson; +import static org.apache.james.util.ClassLoaderUtils.getSystemResourceAsString; +import static org.assertj.core.api.Assertions.assertThat; + +import java.time.Instant; +import java.util.Date; + +import javax.mail.MessagingException; + +import org.apache.james.blob.api.HashBlobId; +import org.apache.james.blob.mail.MimeMessagePartsId; +import org.apache.james.server.core.MailImpl; +import org.apache.mailet.PerRecipientHeaders; +import org.apache.mailet.base.MailAddressFixture; +import org.apache.mailet.base.test.FakeMail; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.datatype.guava.GuavaModule; +import com.fasterxml.jackson.datatype.jdk8.Jdk8Module; +import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; + +class MailDTOTest { + static final HashBlobId.Factory BLOB_ID_FACTORY = new HashBlobId.Factory(); + static final Date LAST_UPDATED = Date.from(Instant.parse("2016-09-08T14:25:52.000Z")); + + private ObjectMapper objectMapper; + + @BeforeEach + void setUp() { + objectMapper = new ObjectMapper() + .registerModule(new Jdk8Module()) + .registerModule(new JavaTimeModule()) + .registerModule(new GuavaModule()); + } + + @Test + void mailDtoShouldBeSerializedToTheRightFormat() throws Exception { + assertThatJson(objectMapper.writeValueAsString(mailDTO1())) + .isEqualTo(getSystemResourceAsString("json/mail1.json")); + } + + @Test + void mailDtoShouldBeDeserializedFromTheRightFormat() throws Exception { + assertThat(objectMapper.readValue(getSystemResourceAsString("json/mail1.json"), MailDTO.class)) + .isEqualTo(mailDTO1()); + } + + @Test + void mailDtoShouldBeSerializedWhenOnlyNameAndBlob() throws Exception { + assertThatJson(objectMapper.writeValueAsString(mailDTOMin())) + .isEqualTo(getSystemResourceAsString("json/mail_min.json")); + } + + @Test + void mailDtoShouldBeDeserializedWhenOnlyNameAndBlob() throws Exception { + assertThat(objectMapper.readValue(getSystemResourceAsString("json/mail_min.json"), MailDTO.class)) + .isEqualTo(mailDTOMin()); + } + + private MailDTO mailDTO1() throws MessagingException { + return MailDTO.fromMail( + FakeMail.builder() + .recipients(MailAddressFixture.RECIPIENT1, MailAddressFixture.RECIPIENT2) + .sender(MailAddressFixture.SENDER) + .attribute("att1", "value") + .errorMessage("an error") + .lastUpdated(LAST_UPDATED) + .remoteHost("toto.com") + .remoteAddr("159.221.12.145") + .addHeaderForRecipient(PerRecipientHeaders.Header.builder() + .name("X-custom-header") + .value("uedcgukrcg") + .build(), MailAddressFixture.RECIPIENT1) + .addHeaderForRecipient(PerRecipientHeaders.Header.builder() + .name("X-custom-header-2") + .value("uedcgukrcg") + .build(), MailAddressFixture.RECIPIENT2) + .state("state") + .name("mail-name-558") + .build(), + MimeMessagePartsId.builder() + .headerBlobId(BLOB_ID_FACTORY.from("210e7136-ede3-44eb-9495-3ed816d6e23b")) + .bodyBlobId(BLOB_ID_FACTORY.from("ef46c026-7819-4048-b562-3a37469191ed")) + .build()); + } + + private MailDTO mailDTOMin() throws MessagingException { + MailImpl mail = new MailImpl(); + mail.setState(null); + mail.setName("mail-name-558"); + mail.setLastUpdated(null); + return MailDTO.fromMail( + mail, + MimeMessagePartsId.builder() + .headerBlobId(BLOB_ID_FACTORY.from("210e7136-ede3-44eb-9495-3ed816d6e23b")) + .bodyBlobId(BLOB_ID_FACTORY.from("ef46c026-7819-4048-b562-3a37469191ed")) + .build()); + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/james-project/blob/f6f9961a/server/queue/queue-rabbitmq/src/test/resources/json/mail1.json ---------------------------------------------------------------------- diff --git a/server/queue/queue-rabbitmq/src/test/resources/json/mail1.json b/server/queue/queue-rabbitmq/src/test/resources/json/mail1.json new file mode 100644 index 0000000..625ed2e --- /dev/null +++ b/server/queue/queue-rabbitmq/src/test/resources/json/mail1.json @@ -0,0 +1,16 @@ +{ + "recipients":["recipient1@localhost","recipient2@localhost"], + "name":"mail-name-558", + "sender":"sender@localhost", + "state":"state", + "errorMessage":"an error", + "lastUpdated":1473344752.000000000, + "attributes":{"att1":"rO0ABXQABXZhbHVl"}, + "remoteAddr":"159.221.12.145", + "remoteHost":"toto.com", + "perRecipientHeaders":{ + "recipient1@localhost":{"header":{"X-custom-header":["uedcgukrcg"]}}, + "recipient2@localhost":{"header":{"X-custom-header-2":["uedcgukrcg"]}}}, + "headerBlobId":"210e7136-ede3-44eb-9495-3ed816d6e23b", + "bodyBlobId":"ef46c026-7819-4048-b562-3a37469191ed" +} http://git-wip-us.apache.org/repos/asf/james-project/blob/f6f9961a/server/queue/queue-rabbitmq/src/test/resources/json/mail_min.json ---------------------------------------------------------------------- diff --git a/server/queue/queue-rabbitmq/src/test/resources/json/mail_min.json b/server/queue/queue-rabbitmq/src/test/resources/json/mail_min.json new file mode 100644 index 0000000..b2b8eea --- /dev/null +++ b/server/queue/queue-rabbitmq/src/test/resources/json/mail_min.json @@ -0,0 +1,14 @@ +{ + "recipients":[], + "name":"mail-name-558", + "sender":null, + "state":null, + "errorMessage":null, + "lastUpdated":null, + "attributes":{}, + "remoteAddr":"127.0.0.1", + "remoteHost":"localhost", + "perRecipientHeaders":{}, + "headerBlobId":"210e7136-ede3-44eb-9495-3ed816d6e23b", + "bodyBlobId":"ef46c026-7819-4048-b562-3a37469191ed" +} --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
