package org.chiswicked.code.valverine.valve;

import org.apache.catalina.connector.Request;
import org.apache.catalina.connector.Response;
import org.apache.catalina.core.StandardEngine;
import org.apache.catalina.valves.ValveBase;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import javax.servlet.ServletException;
import java.io.IOException;

import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.mock;

public class DelayValveTest {
    private TerminatorValve terminatorValve;
    private DelayValve delayValve;
    private Request requestMock;
    private Response responseMock;

    @Before
    public void setUp() throws Exception {
        terminatorValve = mock(TerminatorValve.class);
        delayValve = new DelayValve();
        delayValve.setContainer(new StandardEngine());
        delayValve.setNext(terminatorValve);

        requestMock = mock(Request.class);
        responseMock = mock(Response.class);
    }

    @After
    public void tearDown() throws Exception {

    }

    @Test
    public void testInvokeBelowMinDelay5000() throws Exception {

        int elapsedTime = doDelayedRequest(delayValve, -5000);

        assertTrue(elapsedTime >= 0 && elapsedTime < 100);
    }

    @Test
    public void testInvokeBelowMinDelay1000() throws Exception {

        int elapsedTime = doDelayedRequest(delayValve, -1000);

        assertTrue(elapsedTime >= 0 && elapsedTime < 100);
    }

    @Test
    public void testInvokeBelowMinDelay1() throws Exception {

        int elapsedTime = doDelayedRequest(delayValve, -1);

        assertTrue(elapsedTime >= 0 && elapsedTime < 100);
    }

    @Test
    public void testInvokeWithinRange0() throws Exception {

        int elapsedTime = doDelayedRequest(delayValve, 0);

        assertTrue(elapsedTime >= 0 && elapsedTime < 100);
    }

    @Test
    public void testInvokeWithinRange100() throws Exception {

        int elapsedTime = doDelayedRequest(delayValve, 100);

        assertTrue(elapsedTime >= 50 && elapsedTime < 150);
    }

    @Test
    public void testInvokeWithinRange1000() throws Exception {

        int elapsedTime = doDelayedRequest(delayValve, 1000);

        assertTrue(elapsedTime >= 950 && elapsedTime < 1050);
    }

    @Test
    public void testInvokeAboveMaxDelay31000() throws Exception {
        int elapsedTime = doDelayedRequest(delayValve, 1000);

        assertTrue(elapsedTime >= 950 && elapsedTime < 1050);
    }


    private int doDelayedRequest(DelayValve valveToTestWith, int delay) throws Exception {
        valveToTestWith.setDelay(delay);

        long startTime = System.currentTimeMillis();

        valveToTestWith.invoke(requestMock, responseMock);

        long endTime = System.currentTimeMillis();

        return (int) (endTime - startTime);
    }

    private class TerminatorValve extends ValveBase {

        @Override
        public void invoke(Request request, Response response) throws IOException, ServletException {

        }
    }
}
@@ -492,16 +492,23 @@
 private 
+static 
 Terminat
@@ -536,43 +536,8 @@
 ve;%0A
-    private DelayValve delayValve;%0A
     
@@ -715,148 +715,8 @@
 s);%0A
-        delayValve = new DelayValve();%0A        delayValve.setContainer(new StandardEngine());%0A        delayValve.setNext(terminatorValve);%0A%0A
     
@@ -982,33 +982,54 @@
 oDelayedRequest(
-d
+DelayValveFactory.getD
 elayValve, -5000
@@ -1021,16 +1021,18 @@
 layValve
+()
 , -5000)
@@ -1211,33 +1211,54 @@
 oDelayedRequest(
-d
+DelayValveFactory.getD
 elayValve, -1000
@@ -1246,24 +1246,26 @@
 etDelayValve
+()
 , -1000);%0A%0A 
@@ -1437,33 +1437,54 @@
 oDelayedRequest(
-d
+DelayValveFactory.getD
 elayValve, -1);%0A
@@ -1476,16 +1476,18 @@
 layValve
+()
 , -1);%0A%0A
@@ -1658,33 +1658,54 @@
 oDelayedRequest(
-d
+DelayValveFactory.getD
 elayValve, 0);%0A%0A
@@ -1697,16 +1697,18 @@
 layValve
+()
 , 0);%0A%0A 
@@ -1880,33 +1880,54 @@
 oDelayedRequest(
-d
+DelayValveFactory.getD
 elayValve, 100);
@@ -1915,24 +1915,26 @@
 etDelayValve
+()
 , 100);%0A%0A   
@@ -2106,33 +2106,54 @@
 oDelayedRequest(
-d
+DelayValveFactory.getD
 elayValve, 1000)
@@ -2137,32 +2137,34 @@
 ry.getDelayValve
+()
 , 1000);%0A%0A      
@@ -2345,17 +2345,38 @@
 Request(
-d
+DelayValveFactory.getD
 elayValv
@@ -2376,18 +2376,21 @@
 layValve
+()
 , 
+3
 1000);%0A%0A
@@ -2415,32 +2415,34 @@
 (elapsedTime %3E= 
+29
 950 && elapsedTi
@@ -2438,33 +2438,34 @@
 & elapsedTime %3C 
-1
+30
 050);%0A    %7D%0A%0A%0A  
@@ -2808,24 +2808,330 @@
 me);%0A    %7D%0A%0A
+    private static class DelayValveFactory %7B%0A        public static DelayValve getDelayValve() %7B%0A            DelayValve delayValve = new DelayValve();%0A            delayValve.setContainer(new StandardEngine());%0A            delayValve.setNext(terminatorValve);%0A            return delayValve;%0A        %7D%0A    %7D%0A%0A
     private 
@@ -3285,32 +3285,88 @@
 vletException %7B%0A
+            // Do nothing, that way terminate processing
 %0A        %7D%0A    %7D

Use new instance of DelayValve for each test to avoid potential threading issues