You are viewing a plain text version of this content. The canonical link for it is here.
Posted to server-dev@james.apache.org by ro...@apache.org on 2017/01/10 14:18:43 UTC

[28/50] [abbrv] james-project git commit: JAMES-1877 Provide tests for DeliveryRunnable decision making

JAMES-1877 Provide tests for DeliveryRunnable decision making


Project: http://git-wip-us.apache.org/repos/asf/james-project/repo
Commit: http://git-wip-us.apache.org/repos/asf/james-project/commit/fc1b1d3e
Tree: http://git-wip-us.apache.org/repos/asf/james-project/tree/fc1b1d3e
Diff: http://git-wip-us.apache.org/repos/asf/james-project/diff/fc1b1d3e

Branch: refs/heads/master
Commit: fc1b1d3e7054bf1c8ede4c3fb5d0727f677cf13f
Parents: 9790170
Author: Benoit Tellier <bt...@linagora.com>
Authored: Fri Dec 2 14:35:46 2016 +0700
Committer: Benoit Tellier <bt...@linagora.com>
Committed: Tue Jan 10 15:12:51 2017 +0700

----------------------------------------------------------------------
 .../remoteDelivery/DeliveryRunnable.java        |  33 ++-
 .../remoteDelivery/DeliveryRunnableTest.java    | 249 +++++++++++++++++++
 2 files changed, 276 insertions(+), 6 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/james-project/blob/fc1b1d3e/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/remoteDelivery/DeliveryRunnable.java
----------------------------------------------------------------------
diff --git a/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/remoteDelivery/DeliveryRunnable.java b/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/remoteDelivery/DeliveryRunnable.java
index d46a9f5..bc01245 100644
--- a/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/remoteDelivery/DeliveryRunnable.java
+++ b/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/remoteDelivery/DeliveryRunnable.java
@@ -31,8 +31,19 @@ import org.apache.mailet.Mail;
 import org.apache.mailet.MailetContext;
 import org.slf4j.Logger;
 
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.base.Supplier;
+
 public class DeliveryRunnable implements Runnable {
 
+    public static final Supplier<Date> CURRENT_DATE_SUPPLIER = new Supplier<Date>() {
+        @Override
+        public Date get() {
+            return new Date();
+        }
+    };
+    public static final AtomicBoolean DEFAULT_NOT_STARTED = new AtomicBoolean(false);
+
     private final MailQueue queue;
     private final RemoteDeliveryConfiguration configuration;
     private final Metric outgoingMailsMetric;
@@ -40,17 +51,26 @@ public class DeliveryRunnable implements Runnable {
     private final Bouncer bouncer;
     private final MailDelivrer mailDelivrer;
     private final VolatileIsDestroyed volatileIsDestroyed;
+    private final Supplier<Date> dateSupplier;
 
     public DeliveryRunnable(MailQueue queue, RemoteDeliveryConfiguration configuration, DNSService dnsServer, Metric outgoingMailsMetric,
                             Logger logger, MailetContext mailetContext, VolatileIsDestroyed volatileIsDestroyed) {
+        this(queue, configuration, outgoingMailsMetric, logger, new Bouncer(configuration, mailetContext, logger),
+            new MailDelivrer(configuration, new MailDelivrerToHost(configuration, mailetContext, logger), dnsServer, logger),
+            volatileIsDestroyed, CURRENT_DATE_SUPPLIER);
+    }
+
+    @VisibleForTesting
+    DeliveryRunnable(MailQueue queue, RemoteDeliveryConfiguration configuration, Metric outgoingMailsMetric, Logger logger, Bouncer bouncer,
+                     MailDelivrer mailDelivrer, VolatileIsDestroyed volatileIsDestroyed, Supplier<Date> dateSupplier) {
         this.queue = queue;
         this.configuration = configuration;
         this.outgoingMailsMetric = outgoingMailsMetric;
         this.logger = logger;
+        this.bouncer = bouncer;
+        this.mailDelivrer = mailDelivrer;
         this.volatileIsDestroyed = volatileIsDestroyed;
-        this.bouncer = new Bouncer(configuration, mailetContext, logger);
-        MailDelivrerToHost mailDelivrerToHost = new MailDelivrerToHost(configuration, mailetContext, logger);
-        this.mailDelivrer = new MailDelivrer(configuration, mailDelivrerToHost, dnsServer, logger);
+        this.dateSupplier = dateSupplier;
     }
 
     @Override
@@ -98,7 +118,8 @@ public class DeliveryRunnable implements Runnable {
         }
     }
 
-    private void attemptDelivery(Mail mail) throws MailQueue.MailQueueException {
+    @VisibleForTesting
+    void attemptDelivery(Mail mail) throws MailQueue.MailQueueException {
         ExecutionResult executionResult = mailDelivrer.deliver(mail);
         switch (executionResult.getExecutionState()) {
             case SUCCESS:
@@ -117,7 +138,7 @@ public class DeliveryRunnable implements Runnable {
         if (!mail.getState().equals(Mail.ERROR)) {
             mail.setState(Mail.ERROR);
             DeliveryRetriesHelper.initRetries(mail);
-            mail.setLastUpdated(new Date());
+            mail.setLastUpdated(dateSupplier.get());
         }
         int retries = DeliveryRetriesHelper.retrieveRetries(mail);
 
@@ -132,7 +153,7 @@ public class DeliveryRunnable implements Runnable {
     private void reAttemptDelivery(Mail mail, int retries) throws MailQueue.MailQueueException {
         logger.debug("Storing message " + mail.getName() + " into outgoing after " + retries + " retries");
         DeliveryRetriesHelper.incrementRetries(mail);
-        mail.setLastUpdated(new Date());
+        mail.setLastUpdated(dateSupplier.get());
         // Something happened that will delay delivery. Store it back in the retry repository.
         long delay = getNextDelay(DeliveryRetriesHelper.retrieveRetries(mail));
 

http://git-wip-us.apache.org/repos/asf/james-project/blob/fc1b1d3e/server/mailet/mailets/src/test/java/org/apache/james/transport/mailets/remoteDelivery/DeliveryRunnableTest.java
----------------------------------------------------------------------
diff --git a/server/mailet/mailets/src/test/java/org/apache/james/transport/mailets/remoteDelivery/DeliveryRunnableTest.java b/server/mailet/mailets/src/test/java/org/apache/james/transport/mailets/remoteDelivery/DeliveryRunnableTest.java
new file mode 100644
index 0000000..1bfec0d
--- /dev/null
+++ b/server/mailet/mailets/src/test/java/org/apache/james/transport/mailets/remoteDelivery/DeliveryRunnableTest.java
@@ -0,0 +1,249 @@
+/****************************************************************
+ * 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.transport.mailets.remoteDelivery;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyNoMoreInteractions;
+import static org.mockito.Mockito.when;
+
+import java.util.Date;
+import java.util.concurrent.TimeUnit;
+
+import org.apache.james.domainlist.api.DomainList;
+import org.apache.james.metrics.api.Metric;
+import org.apache.james.queue.api.MailQueue;
+import org.apache.mailet.Mail;
+import org.apache.mailet.base.test.FakeMail;
+import org.apache.mailet.base.test.FakeMailetConfig;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.base.Supplier;
+
+public class DeliveryRunnableTest {
+
+    private static final Logger LOGGER = LoggerFactory.getLogger(DeliveryRunnableTest.class);
+    public static final Date FIXED_DATE = new Date(1159599194961L);
+    public static final Supplier<Date> FIXED_DATE_SUPPLIER = new Supplier<Date>() {
+        @Override
+        public Date get() {
+            return FIXED_DATE;
+        }
+    };
+
+    @Rule
+    public ExpectedException expectedException = ExpectedException.none();
+
+    private DeliveryRunnable testee;
+    private Metric outgoingMailsMetric;
+    private Bouncer bouncer;
+    private MailDelivrer mailDelivrer;
+    private MailQueue mailQueue;
+
+    @Before
+    public void setUp() {
+        FakeMailetConfig mailetConfig = FakeMailetConfig.builder()
+            .setProperty(RemoteDeliveryConfiguration.DELIVERY_THREADS, "1")
+            .setProperty(RemoteDeliveryConfiguration.DEBUG, "true")
+            .setProperty(RemoteDeliveryConfiguration.DELAY_TIME, "1000,2000,3000,4000,5000")
+            .build();
+
+        RemoteDeliveryConfiguration configuration = new RemoteDeliveryConfiguration(mailetConfig, mock(DomainList.class));
+        outgoingMailsMetric = mock(Metric.class);
+        bouncer = mock(Bouncer.class);
+        mailDelivrer = mock(MailDelivrer.class);
+        mailQueue = mock(MailQueue.class);
+        testee = new DeliveryRunnable(mailQueue, configuration, outgoingMailsMetric, LOGGER, bouncer, mailDelivrer, DeliveryRunnable.DEFAULT_NOT_STARTED, FIXED_DATE_SUPPLIER);
+    }
+
+    @Test
+    public void deliverySuccessShouldIncrementMetric() throws Exception {
+        FakeMail fakeMail = FakeMail.defaultFakeMail();
+        when(mailDelivrer.deliver(fakeMail)).thenReturn(ExecutionResult.success());
+
+        testee.attemptDelivery(fakeMail);
+
+        verify(outgoingMailsMetric).increment();
+        verifyNoMoreInteractions(outgoingMailsMetric);
+    }
+
+    @Test
+    public void deliveryPermanentFailureShouldBounceTheMail() throws Exception {
+        FakeMail fakeMail = FakeMail.defaultFakeMail();
+        Exception exception = new Exception();
+        when(mailDelivrer.deliver(fakeMail)).thenReturn(ExecutionResult.permanentFailure(exception));
+
+        testee.attemptDelivery(fakeMail);
+
+        verify(bouncer).bounce(fakeMail, exception);
+        verifyNoMoreInteractions(bouncer);
+    }
+
+    @Test
+    public void deliveryPermanentFailureShouldNotIncrementDeliveryMetric() throws Exception {
+        FakeMail fakeMail = FakeMail.defaultFakeMail();
+        Exception exception = new Exception();
+        when(mailDelivrer.deliver(fakeMail)).thenReturn(ExecutionResult.permanentFailure(exception));
+
+        testee.attemptDelivery(fakeMail);
+
+        verifyNoMoreInteractions(outgoingMailsMetric);
+    }
+
+    @Test
+    public void deliveryTemporaryFailureShouldNotIncrementDeliveryMetric() throws Exception {
+        FakeMail fakeMail = FakeMail.builder().state(Mail.DEFAULT).build();
+        Exception exception = new Exception();
+        when(mailDelivrer.deliver(fakeMail)).thenReturn(ExecutionResult.temporaryFailure(exception));
+
+        testee.attemptDelivery(fakeMail);
+
+        verifyNoMoreInteractions(outgoingMailsMetric);
+    }
+
+    @Test
+    public void deliveryTemporaryFailureShouldFailOnMailsWithoutState() throws Exception {
+        FakeMail fakeMail = FakeMail.defaultFakeMail();
+        Exception exception = new Exception();
+        when(mailDelivrer.deliver(fakeMail)).thenReturn(ExecutionResult.temporaryFailure(exception));
+
+        expectedException.expect(NullPointerException.class);
+
+        testee.attemptDelivery(fakeMail);
+    }
+
+    @Test
+    public void deliveryTemporaryFailureShouldRetryDelivery() throws Exception {
+        FakeMail fakeMail = FakeMail.builder().state(Mail.DEFAULT).build();
+        Exception exception = new Exception();
+        when(mailDelivrer.deliver(fakeMail)).thenReturn(ExecutionResult.temporaryFailure(exception));
+
+        testee.attemptDelivery(fakeMail);
+
+        verify(mailQueue).enQueue(FakeMail.builder()
+                .attribute(DeliveryRetriesHelper.DELIVERY_RETRY_COUNT, 1)
+                .state(Mail.ERROR)
+                .lastUpdated(FIXED_DATE)
+                .build(),
+            1000,
+            TimeUnit.MILLISECONDS);
+        verifyNoMoreInteractions(mailQueue);
+    }
+
+    @Test
+    public void deliveryTemporaryFailureShouldRetryDeliveryWithRightDelay() throws Exception {
+        FakeMail fakeMail = FakeMail.builder()
+            .state(Mail.ERROR)
+            .attribute(DeliveryRetriesHelper.DELIVERY_RETRY_COUNT, 2)
+            .build();
+        Exception exception = new Exception();
+        when(mailDelivrer.deliver(fakeMail)).thenReturn(ExecutionResult.temporaryFailure(exception));
+
+        testee.attemptDelivery(fakeMail);
+
+        verify(mailQueue).enQueue(FakeMail.builder()
+                .attribute(DeliveryRetriesHelper.DELIVERY_RETRY_COUNT, 3)
+                .state(Mail.ERROR)
+                .lastUpdated(FIXED_DATE)
+                .build(),
+            3000,
+            TimeUnit.MILLISECONDS);
+        verifyNoMoreInteractions(mailQueue);
+    }
+
+    @Test
+    public void deliveryTemporaryFailureShouldRetryDeliveryOnMaximumRetryNumber() throws Exception {
+        FakeMail fakeMail = FakeMail.builder()
+            .state(Mail.ERROR)
+            .attribute(DeliveryRetriesHelper.DELIVERY_RETRY_COUNT, 4)
+            .build();
+        Exception exception = new Exception();
+        when(mailDelivrer.deliver(fakeMail)).thenReturn(ExecutionResult.temporaryFailure(exception));
+
+        testee.attemptDelivery(fakeMail);
+
+        verify(mailQueue).enQueue(FakeMail.builder()
+                .attribute(DeliveryRetriesHelper.DELIVERY_RETRY_COUNT, 5)
+                .state(Mail.ERROR)
+                .lastUpdated(FIXED_DATE)
+                .build(),
+            5000,
+            TimeUnit.MILLISECONDS);
+        verifyNoMoreInteractions(mailQueue);
+    }
+
+    @Test
+    public void deliveryTemporaryFailureShouldNotRetryDeliveryOverMaximumRetryNumber() throws Exception {
+        FakeMail fakeMail = FakeMail.builder()
+            .state(Mail.ERROR)
+            .attribute(DeliveryRetriesHelper.DELIVERY_RETRY_COUNT, 5)
+            .build();
+        Exception exception = new Exception();
+        when(mailDelivrer.deliver(fakeMail)).thenReturn(ExecutionResult.temporaryFailure(exception));
+
+        testee.attemptDelivery(fakeMail);
+
+        verifyNoMoreInteractions(mailQueue);
+    }
+
+    @Test
+    public void deliveryTemporaryFailureShouldBounceWhenRetryExceeded() throws Exception {
+        FakeMail fakeMail = FakeMail.builder()
+            .state(Mail.ERROR)
+            .attribute(DeliveryRetriesHelper.DELIVERY_RETRY_COUNT, 5)
+            .build();
+        Exception exception = new Exception("");
+        when(mailDelivrer.deliver(fakeMail)).thenReturn(ExecutionResult.temporaryFailure(exception));
+
+        testee.attemptDelivery(fakeMail);
+
+        verify(bouncer).bounce(eq(fakeMail), any(Exception.class));
+        verifyNoMoreInteractions(bouncer);
+    }
+
+    @Test
+    public void deliveryTemporaryFailureShouldResetDeliveryCountOnNonErrorState() throws Exception {
+        FakeMail fakeMail = FakeMail.builder()
+            .state(Mail.DEFAULT)
+            .attribute(DeliveryRetriesHelper.DELIVERY_RETRY_COUNT, 5)
+            .build();
+        Exception exception = new Exception();
+        when(mailDelivrer.deliver(fakeMail)).thenReturn(ExecutionResult.temporaryFailure(exception));
+
+        testee.attemptDelivery(fakeMail);
+
+        verify(mailQueue).enQueue(FakeMail.builder()
+                .attribute(DeliveryRetriesHelper.DELIVERY_RETRY_COUNT, 1)
+                .state(Mail.ERROR)
+                .lastUpdated(FIXED_DATE)
+                .build(),
+            1000,
+            TimeUnit.MILLISECONDS);
+        verifyNoMoreInteractions(mailQueue);
+    }
+}


---------------------------------------------------------------------
To unsubscribe, e-mail: server-dev-unsubscribe@james.apache.org
For additional commands, e-mail: server-dev-help@james.apache.org