This is an automated email from the ASF dual-hosted git repository.

btellier pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/james-project.git

commit 77bc6458388abb3491cbb3ed6de351f4df656aae
Author: Tran Tien Duc <[email protected]>
AuthorDate: Thu Aug 22 14:51:39 2019 +0700

    JAMES-2865 MockSMTPServer with mock behaviors
    
     - Condition filtering will be tested later
     - Counting Number of Anwsers is not implemented
---
 .../james/mock/smtp/server/MockMessageHandler.java | 81 +++++++++++++++++---
 .../james/mock/smtp/server/MockSMTPServer.java     | 16 +++-
 .../james/mock/smtp/server/MockSMTPServerTest.java | 87 ++++++++++++++++++++--
 .../org/apache/james/utils/SMTPMessageSender.java  |  2 +-
 4 files changed, 167 insertions(+), 19 deletions(-)

diff --git 
a/server/mailet/mock-smtp-server/src/main/java/org/apache/james/mock/smtp/server/MockMessageHandler.java
 
b/server/mailet/mock-smtp-server/src/main/java/org/apache/james/mock/smtp/server/MockMessageHandler.java
index 7322fa7..15323ec 100644
--- 
a/server/mailet/mock-smtp-server/src/main/java/org/apache/james/mock/smtp/server/MockMessageHandler.java
+++ 
b/server/mailet/mock-smtp-server/src/main/java/org/apache/james/mock/smtp/server/MockMessageHandler.java
@@ -22,51 +22,92 @@ package org.apache.james.mock.smtp.server;
 import java.io.IOException;
 import java.io.InputStream;
 import java.nio.charset.StandardCharsets;
+import java.util.List;
+import java.util.Optional;
 
 import javax.mail.internet.AddressException;
 
 import org.apache.commons.io.IOUtils;
+import org.apache.commons.lang3.NotImplementedException;
 import org.apache.james.core.MailAddress;
 import org.apache.james.mock.smtp.server.model.Mail;
+import org.apache.james.mock.smtp.server.model.MockSMTPBehavior;
+import org.apache.james.mock.smtp.server.model.Response;
+import org.apache.james.mock.smtp.server.model.SMTPCommand;
 import org.subethamail.smtp.MessageHandler;
 import org.subethamail.smtp.RejectException;
 import org.subethamail.smtp.TooMuchDataException;
 
 public class MockMessageHandler implements MessageHandler {
 
+    @FunctionalInterface
+    interface Behavior<T> {
+        void behave(T input) throws RejectException;
+    }
+
+    class MockBehavior<T> implements Behavior<T> {
+
+        private final MockSMTPBehavior behavior;
+
+        MockBehavior(MockSMTPBehavior behavior) {
+            this.behavior = behavior;
+        }
+
+        @Override
+        public void behave(T input) throws RejectException {
+            Response response = behavior.getResponse();
+            if (response.isServerRejected()) {
+                throw new RejectException(response.getCode().getRawCode(), 
response.getMessage());
+            }
+            throw new NotImplementedException("Not rejecting commands in mock 
behaviours is not supported yet");
+        }
+    }
+
     private static final int ARGUMENT_SYNTAX_ERROR_501 = 501;
 
     private final Mail.Envelope.Builder envelopeBuilder;
     private final Mail.Builder mailBuilder;
     private final ReceivedMailRepository mailRepository;
+    private final List<MockSMTPBehavior> behaviors;
 
-    MockMessageHandler(ReceivedMailRepository mailRepository) {
+    MockMessageHandler(ReceivedMailRepository mailRepository, 
List<MockSMTPBehavior> behaviors) {
         this.mailRepository = mailRepository;
+        this.behaviors = behaviors;
         this.envelopeBuilder = new Mail.Envelope.Builder();
         this.mailBuilder = new Mail.Builder();
     }
 
     @Override
     public void from(String from) throws RejectException {
-        try {
-            envelopeBuilder.from(new MailAddress(from));
-        } catch (AddressException e) {
-            throw new RejectException(ARGUMENT_SYNTAX_ERROR_501, "invalid 
email address supplied");
-        }
+        Behavior<MailAddress> fromBehavior = 
firstMatchedBehavior(SMTPCommand.MAIL_FROM)
+            .<Behavior<MailAddress>>map(MockBehavior::new)
+            .orElseGet(() -> envelopeBuilder::from);
+
+        fromBehavior.behave(parse(from));
     }
 
     @Override
     public void recipient(String recipient) throws RejectException {
-        try {
-            envelopeBuilder.addRecipient(new MailAddress(recipient));
-        } catch (AddressException e) {
-            throw new RejectException(ARGUMENT_SYNTAX_ERROR_501, "invalid 
email address supplied");
-        }
+        Behavior<MailAddress> recipientBehavior = 
firstMatchedBehavior(SMTPCommand.RCPT_TO)
+            .<Behavior<MailAddress>>map(MockBehavior::new)
+            .orElseGet(() -> envelopeBuilder::addRecipient);
+
+        recipientBehavior.behave(parse(recipient));
     }
 
     @Override
     public void data(InputStream data) throws RejectException, 
TooMuchDataException, IOException {
-        mailBuilder.message(IOUtils.toString(data, StandardCharsets.UTF_8));
+        Behavior<InputStream> dataBehavior = 
firstMatchedBehavior(SMTPCommand.DATA)
+            .<Behavior<InputStream>>map(MockBehavior::new)
+            .orElseGet(() -> content -> 
mailBuilder.message(readData(content)));
+
+        dataBehavior.behave(data);
+    }
+
+    private Optional<MockSMTPBehavior> firstMatchedBehavior(SMTPCommand data) {
+        return behaviors.stream()
+            .filter(behavior -> behavior.getCommand().equals(data))
+            .findFirst();
     }
 
     @Override
@@ -75,4 +116,20 @@ public class MockMessageHandler implements MessageHandler {
             .build();
         mailRepository.store(mail);
     }
+
+    private String readData(InputStream data) {
+        try {
+            return IOUtils.toString(data, StandardCharsets.UTF_8);
+        } catch (IOException e) {
+            throw new RejectException(ARGUMENT_SYNTAX_ERROR_501, "invalid data 
supplied");
+        }
+    }
+
+    private MailAddress parse(String mailAddress) {
+        try {
+            return new MailAddress(mailAddress);
+        } catch (AddressException e) {
+            throw new RejectException(ARGUMENT_SYNTAX_ERROR_501, "invalid 
email address supplied");
+        }
+    }
 }
diff --git 
a/server/mailet/mock-smtp-server/src/main/java/org/apache/james/mock/smtp/server/MockSMTPServer.java
 
b/server/mailet/mock-smtp-server/src/main/java/org/apache/james/mock/smtp/server/MockSMTPServer.java
index 96246c4..9f05e25 100644
--- 
a/server/mailet/mock-smtp-server/src/main/java/org/apache/james/mock/smtp/server/MockSMTPServer.java
+++ 
b/server/mailet/mock-smtp-server/src/main/java/org/apache/james/mock/smtp/server/MockSMTPServer.java
@@ -19,9 +19,12 @@
 
 package org.apache.james.mock.smtp.server;
 
+import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.List;
 
 import org.apache.james.mock.smtp.server.model.Mail;
+import org.apache.james.mock.smtp.server.model.MockSMTPBehavior;
 import org.apache.james.util.Port;
 import org.subethamail.smtp.server.SMTPServer;
 
@@ -29,10 +32,12 @@ class MockSMTPServer {
 
     private final SMTPServer server;
     private final ReceivedMailRepository mailRepository;
+    private final List<MockSMTPBehavior> behaviors;
 
     MockSMTPServer() {
+        this.behaviors = new ArrayList<>();
         this.mailRepository = new ReceivedMailRepository();
-        this.server = new SMTPServer(ctx -> new 
MockMessageHandler(mailRepository));
+        this.server = new SMTPServer(ctx -> new 
MockMessageHandler(mailRepository, behaviors));
         this.server.setPort(0);
     }
 
@@ -52,5 +57,14 @@ class MockSMTPServer {
 
     void stop() {
         server.stop();
+        clearBehavior();
+    }
+
+    void setBehaviors(MockSMTPBehavior... behaviors) {
+        this.behaviors.addAll(Arrays.asList(behaviors));
+    }
+
+    private void clearBehavior() {
+        behaviors.clear();
     }
 }
diff --git 
a/server/mailet/mock-smtp-server/src/test/java/org/apache/james/mock/smtp/server/MockSMTPServerTest.java
 
b/server/mailet/mock-smtp-server/src/test/java/org/apache/james/mock/smtp/server/MockSMTPServerTest.java
index c2c5bdc..4e9cb09 100644
--- 
a/server/mailet/mock-smtp-server/src/test/java/org/apache/james/mock/smtp/server/MockSMTPServerTest.java
+++ 
b/server/mailet/mock-smtp-server/src/test/java/org/apache/james/mock/smtp/server/MockSMTPServerTest.java
@@ -23,6 +23,10 @@ import static 
org.apache.james.mock.smtp.server.Fixture.ALICE;
 import static org.apache.james.mock.smtp.server.Fixture.BOB;
 import static org.apache.james.mock.smtp.server.Fixture.DOMAIN;
 import static org.apache.james.mock.smtp.server.Fixture.JACK;
+import static 
org.apache.james.mock.smtp.server.model.Response.SMTPStatusCode.SERVICE_NOT_AVAILABLE_421;
+import static org.apache.james.mock.smtp.server.model.SMTPCommand.DATA;
+import static org.apache.james.mock.smtp.server.model.SMTPCommand.MAIL_FROM;
+import static org.apache.james.mock.smtp.server.model.SMTPCommand.RCPT_TO;
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.assertj.core.api.Assertions.assertThatCode;
 import static org.assertj.core.api.Assertions.assertThatThrownBy;
@@ -32,9 +36,12 @@ import java.util.List;
 
 import javax.mail.internet.MimeMessage;
 
+import org.apache.commons.net.smtp.SMTPConnectionClosedException;
 import org.apache.james.core.MailAddress;
 import org.apache.james.core.builder.MimeMessageBuilder;
+import org.apache.james.mock.smtp.server.model.Condition;
 import org.apache.james.mock.smtp.server.model.Mail;
+import org.apache.james.mock.smtp.server.model.MockSMTPBehavior;
 import org.apache.james.mock.smtp.server.model.Response;
 import org.apache.james.util.MimeMessageUtil;
 import org.apache.james.util.Port;
@@ -52,8 +59,6 @@ import com.github.fge.lambdas.Throwing;
 
 class MockSMTPServerTest {
 
-    private static final Response.SMTPStatusCode SERVICE_NOT_AVAILABLE_421 = 
Response.SMTPStatusCode.of(421);
-
     @Nested
     class NormalBehaviorTests {
         private MockSMTPServer mockServer;
@@ -75,9 +80,9 @@ class MockSMTPServerTest {
                 .connect("localhost", mockServer.getPort());
 
             MimeMessage message = MimeMessageBuilder.mimeMessageBuilder()
-            .setSubject("test")
-            .setText("any text")
-            .build();
+                .setSubject("test")
+                .setText("any text")
+                .build();
 
             FakeMail mail = FakeMail.builder()
                 .name("name")
@@ -104,6 +109,78 @@ class MockSMTPServerTest {
         }
     }
 
+    @Nested
+    class MailMockBehaviorTest {
+        private MockSMTPServer mockServer;
+        private FakeMail mail1;
+        private MimeMessage mimeMessage1;
+        private SMTPMessageSender smtpClient;
+
+        @BeforeEach
+        void setUp() throws Exception {
+            mockServer = new MockSMTPServer();
+
+            mimeMessage1 = MimeMessageBuilder.mimeMessageBuilder()
+                .setSubject("test")
+                .setText("any text")
+                .build();
+            mail1 = FakeMail.builder()
+                .name("name")
+                .sender(BOB)
+                .recipients(ALICE, JACK)
+                .mimeMessage(mimeMessage1)
+                .build();
+
+            mockServer.start();
+            smtpClient = new SMTPMessageSender(DOMAIN)
+                .connect("localhost", mockServer.getPort());
+        }
+
+        @AfterEach
+        void tearDown() {
+            mockServer.stop();
+        }
+
+        @Test
+        void serverShouldReceiveMessageFromClient() throws Exception {
+            mockServer.setBehaviors(new MockSMTPBehavior(
+                MAIL_FROM,
+                Condition.MATCH_ALL,
+                Response.serverReject(SERVICE_NOT_AVAILABLE_421, "mock 
response"),
+                MockSMTPBehavior.NumberOfAnswersPolicy.anytime()));
+
+            assertThatThrownBy(() -> smtpClient.sendMessage(mail1))
+                .isInstanceOf(SMTPConnectionClosedException.class)
+                .hasMessageContaining("421");
+        }
+
+        @Test
+        void serverShouldReceiveMessageRecipientClient() throws Exception {
+            mockServer.setBehaviors(new MockSMTPBehavior(
+                RCPT_TO,
+                Condition.MATCH_ALL,
+                Response.serverReject(SERVICE_NOT_AVAILABLE_421, "mock 
response"),
+                MockSMTPBehavior.NumberOfAnswersPolicy.anytime()));
+
+            assertThatThrownBy(() -> smtpClient.sendMessage(mail1))
+                .isInstanceOf(SMTPConnectionClosedException.class)
+                .hasMessageContaining("421");
+        }
+
+        @Test
+        void serverShouldReceiveMessageDataClient() throws Exception {
+            mockServer.setBehaviors(new MockSMTPBehavior(
+                DATA,
+                Condition.MATCH_ALL,
+                Response.serverReject(SERVICE_NOT_AVAILABLE_421, "mock 
response"),
+                MockSMTPBehavior.NumberOfAnswersPolicy.anytime()));
+
+            assertThatThrownBy(() -> smtpClient.sendMessage(mail1))
+                .isInstanceOf(SMTPConnectionClosedException.class)
+                .hasMessageContaining("421");
+        }
+    }
+
     @Test
     void serverStartShouldOpenASmtpPort() {
         MockSMTPServer mockServer = new MockSMTPServer();
diff --git 
a/server/testing/src/main/java/org/apache/james/utils/SMTPMessageSender.java 
b/server/testing/src/main/java/org/apache/james/utils/SMTPMessageSender.java
index 7a249b8..cdae5c8 100644
--- a/server/testing/src/main/java/org/apache/james/utils/SMTPMessageSender.java
+++ b/server/testing/src/main/java/org/apache/james/utils/SMTPMessageSender.java
@@ -119,7 +119,7 @@ public class SMTPMessageSender extends ExternalResource 
implements Closeable {
         doSetSender(from);
         mail.getRecipients().stream()
             .map(MailAddress::asString)
-            .forEach(Throwing.consumer(this::doAddRcpt));
+            .forEach(Throwing.consumer(this::doAddRcpt).sneakyThrow());
         doData(asString(mail.getMessage()));
         return this;
     }


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to