package org.webpieces.httpfrontend.api; import java.net.InetSocketAddress; import java.nio.ByteBuffer; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeoutException; import org.junit.Assert; import org.junit.Before; import org.junit.Test; import org.webpieces.asyncserver.api.AsyncServerManager; import org.webpieces.asyncserver.api.AsyncServerMgrFactory; import org.webpieces.data.api.BufferCreationPool; import org.webpieces.frontend.api.FrontendConfig; import org.webpieces.frontend.api.HttpFrontendFactory; import org.webpieces.frontend.api.HttpFrontendManager; import org.webpieces.frontend.api.HttpServer; import org.webpieces.httpparser.api.HttpParser; import org.webpieces.httpparser.api.HttpParserFactory; import org.webpieces.httpparser.api.dto.HttpRequest; import org.webpieces.httpparser.api.dto.HttpRequestLine; import org.webpieces.httpparser.api.dto.HttpUri; import org.webpieces.httpparser.api.dto.KnownHttpMethod; import org.webpieces.mock.ParametersPassedIn; import org.webpieces.nio.api.handlers.ConnectionListener; import org.webpieces.nio.api.handlers.DataListener; public class TestTimeoutConnection { private MockTcpChannel mockServerChannel = new MockTcpChannel(); private MockTcpServerChannel mockChannel = new MockTcpServerChannel(); private MockChannelManager mockChanMgr = new MockChannelManager(); private MockTimer timer = new MockTimer(); private RequestListenerForTest requestListenerForTest = new RequestListenerForTest(); private HttpFrontendManager mgr; @Before public void setup() { mockChanMgr.addTcpSvrChannel(mockChannel); AsyncServerManager svrManager = AsyncServerMgrFactory.createAsyncServer(mockChanMgr); BufferCreationPool pool = new BufferCreationPool(); mgr = HttpFrontendFactory.createFrontEnd(svrManager, timer, pool); } /** * This tests by mocking channelmanager out such that we have full control INCLUDING the ability to throw * any exceptions we want... */ @Test public void testNoWriteDataTimeout() throws InterruptedException, ExecutionException, TimeoutException { long timeout = 6000; FrontendConfig config = new FrontendConfig("httpFrontend", new InetSocketAddress(80)); config.maxConnectToRequestTimeoutMs = (int) timeout; HttpServer server = mgr.createHttpServer(config , requestListenerForTest); server.start(); ConnectionListener[] listeners = mockChanMgr.fetchTcpConnectionListeners(); Assert.assertEquals(1, listeners.length); MockFuture<?> mockFuture = new MockFuture<>(); timer.addMockFuture(mockFuture); ConnectionListener listener = listeners[0]; listener.connected(mockServerChannel, true); //expect timer task to be scheduled... ParametersPassedIn[] methodCalls = timer.getScheduledTimers(); Assert.assertEquals("Expecting that timer.schedule is called once", 1, methodCalls.length); ParametersPassedIn call = methodCalls[0]; Runnable timerTask = (Runnable) call.getArgs()[0]; long time = (Long)call.getArgs()[1]; Assert.assertEquals(timeout, time); //now, simulate the timeout timerTask.run(); //verify our connection was closed Assert.assertTrue(mockServerChannel.isClosed()); //verify our timeout was not cancelled.. Assert.assertTrue(!mockFuture.isCancelled()); } @Test public void testTimeoutTimerCancelled() throws InterruptedException, ExecutionException { long timeout = 6000; FrontendConfig config = new FrontendConfig("httpFrontend", new InetSocketAddress(80)); config.maxConnectToRequestTimeoutMs = (int) timeout; HttpServer server = mgr.createHttpServer(config , requestListenerForTest); server.start(); ConnectionListener[] listeners = mockChanMgr.fetchTcpConnectionListeners(); Assert.assertEquals(1, listeners.length); MockFuture<?> mockFuture = new MockFuture<>(); timer.addMockFuture(mockFuture); ConnectionListener listener = listeners[0]; CompletableFuture<DataListener> future = listener.connected(mockServerChannel, true); //expect timer task to be scheduled... ParametersPassedIn[] methodCalls = timer.getScheduledTimers(); Assert.assertEquals("Expecting that timer.schedule is called once", 1, methodCalls.length); DataListener dataListener = future.get(); ByteBuffer buffer = createHttpRequest(); dataListener.incomingData(mockServerChannel, buffer); //verify our connection was not closed Assert.assertTrue(!mockServerChannel.isClosed()); //verify our timeout was cancelled.. Assert.assertTrue(mockFuture.isCancelled()); } private byte[] unwrap(ByteBuffer buffer) { byte[] data = new byte[buffer.remaining()]; buffer.get(data); return data; } private ByteBuffer createHttpRequest() { HttpRequestLine requestLine = new HttpRequestLine(); requestLine.setMethod(KnownHttpMethod.POST); requestLine.setUri(new HttpUri("http://myhost.com")); HttpRequest request = new HttpRequest(); request.setRequestLine(requestLine); HttpParser parser = HttpParserFactory.createParser(new BufferCreationPool()); byte[] bytes = unwrap(parser.marshalToByteBuffer(request)); return ByteBuffer.wrap(bytes); } }