package org.eclipse.jetty.client; import java.net.ServerSocket; import java.net.Socket; import java.util.concurrent.RejectedExecutionException; import org.junit.Assert; import org.junit.BeforeClass; import org.junit.Test; public class HttpDestinationQueueTest { private static HttpClient _httpClient; private static long _timeout = 200; @BeforeClass public static void beforeOnce() throws Exception { _httpClient = new HttpClient(); _httpClient.setMaxConnectionsPerAddress(1); _httpClient.setMaxQueueSizePerAddress(1); _httpClient.setTimeout(_timeout); _httpClient.start(); } @Test public void testDestinationMaxQueueSize() throws Exception { ServerSocket server = new ServerSocket(0); // This will keep the connection busy HttpExchange exchange1 = new HttpExchange(); exchange1.setMethod("GET"); exchange1.setURL("http://localhost:" + server.getLocalPort() + "/exchange1"); _httpClient.send(exchange1); // Read request so we are sure that this exchange is out of the queue Socket socket = server.accept(); byte[] buffer = new byte[1024]; StringBuilder request = new StringBuilder(); while (true) { int read = socket.getInputStream().read(buffer); request.append(new String(buffer,0,read,"UTF-8")); if (request.toString().endsWith("\r\n\r\n")) break; } Assert.assertTrue(request.toString().contains("exchange1")); // This will be queued HttpExchange exchange2 = new HttpExchange(); exchange2.setMethod("GET"); exchange2.setURL("http://localhost:" + server.getLocalPort() + "/exchange2"); _httpClient.send(exchange2); // This will be rejected, since the connection is busy and the queue is full HttpExchange exchange3 = new HttpExchange(); exchange3.setMethod("GET"); exchange3.setURL("http://localhost:" + server.getLocalPort() + "/exchange3"); try { _httpClient.send(exchange3); Assert.fail(); } catch (RejectedExecutionException x) { // Expected } // Send the response to avoid exceptions in the console socket.getOutputStream().write("HTTP/1.1 200 OK\r\nContent-Length: 0\r\n\r\n".getBytes("UTF-8")); Assert.assertEquals(HttpExchange.STATUS_COMPLETED,exchange1.waitForDone()); // Be sure that the second exchange can be sent request.setLength(0); while (true) { int read = socket.getInputStream().read(buffer); request.append(new String(buffer,0,read,"UTF-8")); if (request.toString().endsWith("\r\n\r\n")) break; } Assert.assertTrue(request.toString().contains("exchange2")); socket.getOutputStream().write("HTTP/1.1 200 OK\r\nConnection: close\r\n\r\n".getBytes("UTF-8")); socket.close(); Assert.assertEquals(HttpExchange.STATUS_COMPLETED,exchange2.waitForDone()); server.close(); } @Test public void testDefaultTimeoutIncludesQueuingExchangeExpiresInQueue() throws Exception { ServerSocket server = new ServerSocket(0); // This will keep the connection busy HttpExchange exchange1 = new HttpExchange(); exchange1.setTimeout(_timeout * 3); // Be sure it does not expire exchange1.setMethod("GET"); exchange1.setURL("http://localhost:" + server.getLocalPort() + "/exchange1"); _httpClient.send(exchange1); // Read request so we are sure that this exchange is out of the queue Socket socket = server.accept(); byte[] buffer = new byte[1024]; StringBuilder request = new StringBuilder(); while (true) { int read = socket.getInputStream().read(buffer); request.append(new String(buffer,0,read,"UTF-8")); if (request.toString().endsWith("\r\n\r\n")) break; } Assert.assertTrue(request.toString().contains("exchange1")); // This will be queued HttpExchange exchange2 = new HttpExchange(); exchange2.setMethod("GET"); exchange2.setURL("http://localhost:" + server.getLocalPort() + "/exchange2"); _httpClient.send(exchange2); // Wait until the queued exchange times out in the queue Thread.sleep(_timeout * 2); Assert.assertEquals(HttpExchange.STATUS_EXPIRED,exchange2.getStatus()); // Send the response to the first exchange to avoid exceptions in the console socket.getOutputStream().write("HTTP/1.1 200 OK\r\nContent-Length: 0\r\n\r\n".getBytes("UTF-8")); Assert.assertEquals(HttpExchange.STATUS_COMPLETED,exchange1.waitForDone()); socket.close(); server.close(); } @Test public void testDefaultTimeoutIncludesQueuingExchangeExpiresDuringRequest() throws Exception { ServerSocket server = new ServerSocket(0); HttpExchange exchange1 = new HttpExchange(); exchange1.setMethod("GET"); exchange1.setURL("http://localhost:" + server.getLocalPort() + "/exchange1"); _httpClient.send(exchange1); // Read request so we are sure that this exchange is out of the queue Socket socket = server.accept(); byte[] buffer = new byte[1024]; StringBuilder request = new StringBuilder(); while (true) { int read = socket.getInputStream().read(buffer); request.append(new String(buffer,0,read,"UTF-8")); if (request.toString().endsWith("\r\n\r\n")) break; } Assert.assertTrue(request.toString().contains("exchange1")); // Wait until the exchange times out during the request Thread.sleep(_timeout * 2); Assert.assertEquals(HttpExchange.STATUS_EXPIRED,exchange1.getStatus()); socket.close(); server.close(); } @Test public void testExchangeTimeoutIncludesQueuingExchangeExpiresDuringResponse() throws Exception { ServerSocket server = new ServerSocket(0); long timeout = 1000; HttpExchange exchange1 = new HttpExchange(); exchange1.setTimeout(timeout); exchange1.setMethod("GET"); exchange1.setURL("http://localhost:" + server.getLocalPort() + "/exchange1"); _httpClient.send(exchange1); // Read request so we are sure that this exchange is out of the queue Socket socket = server.accept(); byte[] buffer = new byte[1024]; StringBuilder request = new StringBuilder(); while (true) { int read = socket.getInputStream().read(buffer); request.append(new String(buffer,0,read,"UTF-8")); if (request.toString().endsWith("\r\n\r\n")) break; } Assert.assertTrue(request.toString().contains("exchange1")); // Write part of the response socket.getOutputStream().write("HTTP/1.1 200 OK\r\nContent-Type: application/octet-stream\r\nContent-Length: 1\r\n\r\n".getBytes("UTF-8")); // Wait until the exchange times out during the response Thread.sleep(timeout * 2); Assert.assertEquals(HttpExchange.STATUS_EXPIRED,exchange1.getStatus()); socket.close(); server.close(); } }