You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@hc.apache.org by ol...@apache.org on 2008/03/12 20:11:14 UTC

svn commit: r636459 - /httpcomponents/httpcore/trunk/module-nio/src/test/java/org/apache/http/nio/protocol/TestThrottlingNHttpHandlers.java

Author: olegk
Date: Wed Mar 12 12:11:10 2008
New Revision: 636459

URL: http://svn.apache.org/viewvc?rev=636459&view=rev
Log:
More test cases for throttling protocol handlers

Modified:
    httpcomponents/httpcore/trunk/module-nio/src/test/java/org/apache/http/nio/protocol/TestThrottlingNHttpHandlers.java

Modified: httpcomponents/httpcore/trunk/module-nio/src/test/java/org/apache/http/nio/protocol/TestThrottlingNHttpHandlers.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpcore/trunk/module-nio/src/test/java/org/apache/http/nio/protocol/TestThrottlingNHttpHandlers.java?rev=636459&r1=636458&r2=636459&view=diff
==============================================================================
--- httpcomponents/httpcore/trunk/module-nio/src/test/java/org/apache/http/nio/protocol/TestThrottlingNHttpHandlers.java (original)
+++ httpcomponents/httpcore/trunk/module-nio/src/test/java/org/apache/http/nio/protocol/TestThrottlingNHttpHandlers.java Wed Mar 12 12:11:10 2008
@@ -51,12 +51,14 @@
 import junit.framework.TestCase;
 import junit.framework.TestSuite;
 
+import org.apache.http.Header;
 import org.apache.http.HttpEntity;
 import org.apache.http.HttpEntityEnclosingRequest;
 import org.apache.http.HttpException;
 import org.apache.http.HttpRequest;
 import org.apache.http.HttpResponse;
 import org.apache.http.HttpStatus;
+import org.apache.http.HttpVersion;
 import org.apache.http.entity.InputStreamEntity;
 import org.apache.http.impl.DefaultConnectionReuseStrategy;
 import org.apache.http.impl.DefaultHttpResponseFactory;
@@ -64,6 +66,7 @@
 import org.apache.http.message.BasicHttpRequest;
 import org.apache.http.mockup.ByteSequence;
 import org.apache.http.mockup.RequestCount;
+import org.apache.http.mockup.ResponseSequence;
 import org.apache.http.mockup.SimpleEventListener;
 import org.apache.http.mockup.SimpleHttpRequestHandlerResolver;
 import org.apache.http.mockup.TestHttpClient;
@@ -92,6 +95,7 @@
 import org.apache.http.protocol.ResponseContent;
 import org.apache.http.protocol.ResponseDate;
 import org.apache.http.protocol.ResponseServer;
+import org.apache.http.util.EncodingUtils;
 import org.apache.http.util.EntityUtils;
 
 /**
@@ -772,4 +776,589 @@
         this.server.getParams().setIntParameter(
                 CoreConnectionPNames.SO_TIMEOUT, originalTimeout);
     }
+    
+    /**
+     * This test case executes a series of simple (non-pipelined) HTTP/1.0
+     * POST requests over multiple persistent connections.
+     */
+    public void testSimpleHttpPostsHTTP10() throws Exception {
+
+        final int connNo = 3;
+        final int reqNo = 20;
+        final RequestCount requestCount = new RequestCount(connNo * reqNo);
+        final ByteSequence requestData = new ByteSequence();
+        requestData.rnd(reqNo);
+
+        List<ByteSequence> responseData = new ArrayList<ByteSequence>(connNo);
+        for (int i = 0; i < connNo; i++) {
+            responseData.add(new ByteSequence());
+        }
+
+        HttpRequestHandler requestHandler = new HttpRequestHandler() {
+
+
+            public void handle(
+                    final HttpRequest request,
+                    final HttpResponse response,
+                    final HttpContext context) throws HttpException, IOException {
+
+                if (request instanceof HttpEntityEnclosingRequest) {
+                    HttpEntity incoming = ((HttpEntityEnclosingRequest) request).getEntity();
+                    byte[] data = EntityUtils.toByteArray(incoming);
+
+                    NByteArrayEntity outgoing = new NByteArrayEntity(data);
+                    outgoing.setChunked(false);
+                    response.setEntity(outgoing);
+                } else {
+                    NStringEntity outgoing = new NStringEntity("No content");
+                    response.setEntity(outgoing);
+                }
+            }
+
+        };
+
+        // Set protocol level to HTTP/1.0
+        this.client.getParams().setParameter(
+                CoreProtocolPNames.PROTOCOL_VERSION, HttpVersion.HTTP_1_0);
+
+        HttpRequestExecutionHandler requestExecutionHandler = new HttpRequestExecutionHandler() {
+
+            public void initalizeContext(final HttpContext context, final Object attachment) {
+                context.setAttribute("LIST", (ByteSequence) attachment);
+                context.setAttribute("REQ-COUNT", new Integer(0));
+                context.setAttribute("RES-COUNT", new Integer(0));
+            }
+
+            public void finalizeContext(final HttpContext context) {
+            }
+
+            public HttpRequest submitRequest(final HttpContext context) {
+                int i = ((Integer) context.getAttribute("REQ-COUNT")).intValue();
+                BasicHttpEntityEnclosingRequest post = null;
+                if (i < reqNo) {
+                    post = new BasicHttpEntityEnclosingRequest("POST", "/?" + i);
+                    byte[] data = requestData.getBytes(i);
+                    NByteArrayEntity outgoing = new NByteArrayEntity(data);
+                    post.setEntity(outgoing);
+
+                    context.setAttribute("REQ-COUNT", new Integer(i + 1));
+                }
+                return post;
+            }
+
+            public void handleResponse(final HttpResponse response, final HttpContext context) {
+                NHttpConnection conn = (NHttpConnection) context.getAttribute(
+                        ExecutionContext.HTTP_CONNECTION);
+
+                ByteSequence list = (ByteSequence) context.getAttribute("LIST");
+                int i = ((Integer) context.getAttribute("RES-COUNT")).intValue();
+                i++;
+                context.setAttribute("RES-COUNT", new Integer(i));
+
+                try {
+                    HttpEntity entity = response.getEntity();
+                    byte[] data = EntityUtils.toByteArray(entity);
+                    list.addBytes(data);
+                    requestCount.decrement();
+                } catch (IOException ex) {
+                    requestCount.abort();
+                    return;
+                }
+
+                if (i < reqNo) {
+                    conn.requestInput();
+                }
+            }
+
+        };
+
+        NHttpServiceHandler serviceHandler = createHttpServiceHandler(
+                requestHandler,
+                null,
+                this.execService);
+
+        NHttpClientHandler clientHandler = createHttpClientHandler(
+                requestExecutionHandler,
+                this.execService);
+
+        this.server.setRequestCount(requestCount);
+        this.client.setRequestCount(requestCount);
+        
+        this.server.start(serviceHandler);
+        this.client.start(clientHandler);
+
+        ListenerEndpoint endpoint = this.server.getListenerEndpoint();
+        endpoint.waitFor();
+        InetSocketAddress serverAddress = (InetSocketAddress) endpoint.getAddress();
+
+        for (int i = 0; i < responseData.size(); i++) {
+            this.client.openConnection(
+                    new InetSocketAddress("localhost", serverAddress.getPort()),
+                    responseData.get(i));
+        }
+
+        requestCount.await(10000);
+        assertEquals(0, requestCount.getValue());
+
+        this.client.shutdown();
+        this.server.shutdown();
+
+        for (int c = 0; c < responseData.size(); c++) {
+            ByteSequence receivedPackets = responseData.get(c);
+            ByteSequence expectedPackets = requestData;
+            assertEquals(expectedPackets.size(), receivedPackets.size());
+            for (int p = 0; p < requestData.size(); p++) {
+                byte[] expected = requestData.getBytes(p);
+                byte[] received = receivedPackets.getBytes(p);
+
+                assertEquals(expected.length, received.length);
+                for (int i = 0; i < expected.length; i++) {
+                    assertEquals(expected[i], received[i]);
+                }
+            }
+        }
+
+    }
+
+    /**
+     * This test case executes a series of simple (non-pipelined) POST requests
+     * over multiple connections using the 'expect: continue' handshake.
+     */
+    public void testHttpPostsWithExpectContinue() throws Exception {
+
+        final int connNo = 3;
+        final int reqNo = 20;
+        final RequestCount requestCount = new RequestCount(connNo * reqNo);
+        final ByteSequence requestData = new ByteSequence();
+        requestData.rnd(reqNo);
+
+        List<ByteSequence> responseData = new ArrayList<ByteSequence>(connNo);
+        for (int i = 0; i < connNo; i++) {
+            responseData.add(new ByteSequence());
+        }
+
+        HttpRequestHandler requestHandler = new HttpRequestHandler() {
+
+            public void handle(
+                    final HttpRequest request,
+                    final HttpResponse response,
+                    final HttpContext context) throws HttpException, IOException {
+
+                if (request instanceof HttpEntityEnclosingRequest) {
+                    HttpEntity incoming = ((HttpEntityEnclosingRequest) request).getEntity();
+                    byte[] data = EntityUtils.toByteArray(incoming);
+                    NByteArrayEntity outgoing = new NByteArrayEntity(data);
+                    outgoing.setChunked(true);
+                    response.setEntity(outgoing);
+                } else {
+                    NStringEntity outgoing = new NStringEntity("No content");
+                    response.setEntity(outgoing);
+                }
+            }
+
+        };
+
+        // Activate 'expect: continue' handshake
+        this.client.getParams().setBooleanParameter(CoreProtocolPNames.USE_EXPECT_CONTINUE, true);
+
+        HttpRequestExecutionHandler requestExecutionHandler = new HttpRequestExecutionHandler() {
+
+            public void initalizeContext(final HttpContext context, final Object attachment) {
+                context.setAttribute("LIST", (ByteSequence) attachment);
+                context.setAttribute("REQ-COUNT", new Integer(0));
+                context.setAttribute("RES-COUNT", new Integer(0));
+            }
+
+            public void finalizeContext(final HttpContext context) {
+            }
+
+            public HttpRequest submitRequest(final HttpContext context) {
+                int i = ((Integer) context.getAttribute("REQ-COUNT")).intValue();
+                BasicHttpEntityEnclosingRequest post = null;
+                if (i < reqNo) {
+                    post = new BasicHttpEntityEnclosingRequest("POST", "/?" + i);
+                    byte[] data = requestData.getBytes(i);
+                    NByteArrayEntity outgoing = new NByteArrayEntity(data);
+                    outgoing.setChunked(true);
+                    post.setEntity(outgoing);
+
+                    context.setAttribute("REQ-COUNT", new Integer(i + 1));
+                }
+                return post;
+            }
+
+            public void handleResponse(final HttpResponse response, final HttpContext context) {
+                NHttpConnection conn = (NHttpConnection) context.getAttribute(
+                        ExecutionContext.HTTP_CONNECTION);
+
+                ByteSequence list = (ByteSequence) context.getAttribute("LIST");
+                int i = ((Integer) context.getAttribute("RES-COUNT")).intValue();
+                i++;
+                context.setAttribute("RES-COUNT", new Integer(i));
+
+                try {
+                    HttpEntity entity = response.getEntity();
+                    byte[] data = EntityUtils.toByteArray(entity);
+                    list.addBytes(data);
+                    requestCount.decrement();
+                } catch (IOException ex) {
+                    requestCount.abort();
+                    return;
+                }
+
+                if (i < reqNo) {
+                    conn.requestInput();
+                }
+            }
+
+        };
+
+        NHttpServiceHandler serviceHandler = createHttpServiceHandler(
+                requestHandler,
+                null,
+                this.execService);
+
+        NHttpClientHandler clientHandler = createHttpClientHandler(
+                requestExecutionHandler,
+                this.execService);
+
+        this.server.setRequestCount(requestCount);
+        this.client.setRequestCount(requestCount);
+        
+        this.server.start(serviceHandler);
+        this.client.start(clientHandler);
+
+        ListenerEndpoint endpoint = this.server.getListenerEndpoint();
+        endpoint.waitFor();
+        InetSocketAddress serverAddress = (InetSocketAddress) endpoint.getAddress();
+
+        for (int i = 0; i < responseData.size(); i++) {
+            this.client.openConnection(
+                    new InetSocketAddress("localhost", serverAddress.getPort()),
+                    responseData.get(i));
+        }
+
+        requestCount.await(10000);
+        assertEquals(0, requestCount.getValue());
+
+        this.client.shutdown();
+        this.server.shutdown();
+
+        for (int c = 0; c < responseData.size(); c++) {
+            ByteSequence receivedPackets = responseData.get(c);
+            ByteSequence expectedPackets = requestData;
+            assertEquals(expectedPackets.size(), receivedPackets.size());
+            for (int p = 0; p < requestData.size(); p++) {
+                byte[] expected = requestData.getBytes(p);
+                byte[] received = receivedPackets.getBytes(p);
+
+                assertEquals(expected.length, received.length);
+                for (int i = 0; i < expected.length; i++) {
+                    assertEquals(expected[i], received[i]);
+                }
+            }
+        }
+
+    }
+
+    /**
+     * This test case executes a series of simple (non-pipelined) POST requests
+     * over multiple connections that do not meet the target server expectations.
+     */
+    public void testHttpPostsWithExpectationVerification() throws Exception {
+
+        final int reqNo = 3;
+        final RequestCount requestCount = new RequestCount(reqNo);
+        final ResponseSequence responses = new ResponseSequence();
+
+        HttpRequestHandler requestHandler = new HttpRequestHandler() {
+
+            public void handle(
+                    final HttpRequest request,
+                    final HttpResponse response,
+                    final HttpContext context) throws HttpException, IOException {
+
+                NStringEntity outgoing = new NStringEntity("No content");
+                response.setEntity(outgoing);
+            }
+
+        };
+
+        HttpExpectationVerifier expectationVerifier = new HttpExpectationVerifier() {
+
+            public void verify(
+                    final HttpRequest request,
+                    final HttpResponse response,
+                    final HttpContext context) throws HttpException {
+                Header someheader = request.getFirstHeader("Secret");
+                if (someheader != null) {
+                    int secretNumber;
+                    try {
+                        secretNumber = Integer.parseInt(someheader.getValue());
+                    } catch (NumberFormatException ex) {
+                        response.setStatusCode(HttpStatus.SC_BAD_REQUEST);
+                        return;
+                    }
+                    if (secretNumber < 2) {
+                        response.setStatusCode(HttpStatus.SC_EXPECTATION_FAILED);
+                        NByteArrayEntity outgoing = new NByteArrayEntity(
+                                EncodingUtils.getAsciiBytes("Wrong secret number"));
+                        response.setEntity(outgoing);
+                    }
+                }
+            }
+
+        };
+
+        // Activate 'expect: continue' handshake
+        this.client.getParams().setBooleanParameter(CoreProtocolPNames.USE_EXPECT_CONTINUE, true);
+
+        HttpRequestExecutionHandler requestExecutionHandler = new HttpRequestExecutionHandler() {
+
+            public void initalizeContext(final HttpContext context, final Object attachment) {
+                context.setAttribute("LIST", (ResponseSequence) attachment);
+                context.setAttribute("REQ-COUNT", new Integer(0));
+                context.setAttribute("RES-COUNT", new Integer(0));
+            }
+
+            public void finalizeContext(final HttpContext context) {
+            }
+
+            public HttpRequest submitRequest(final HttpContext context) {
+                int i = ((Integer) context.getAttribute("REQ-COUNT")).intValue();
+                BasicHttpEntityEnclosingRequest post = null;
+                if (i < reqNo) {
+                    post = new BasicHttpEntityEnclosingRequest("POST", "/");
+                    post.addHeader("Secret", Integer.toString(i));
+                    NByteArrayEntity outgoing = new NByteArrayEntity(
+                            EncodingUtils.getAsciiBytes("No content"));
+                    post.setEntity(outgoing);
+
+                    context.setAttribute("REQ-COUNT", new Integer(i + 1));
+                }
+                return post;
+            }
+
+            public void handleResponse(final HttpResponse response, final HttpContext context) {
+                NHttpConnection conn = (NHttpConnection) context.getAttribute(
+                        ExecutionContext.HTTP_CONNECTION);
+
+                ResponseSequence list = (ResponseSequence) context.getAttribute("LIST");
+                int i = ((Integer) context.getAttribute("RES-COUNT")).intValue();
+                i++;
+                context.setAttribute("RES-COUNT", new Integer(i));
+
+                HttpEntity entity = response.getEntity();
+                if (entity != null) {
+                    try {
+                        entity.consumeContent();
+                    } catch (IOException ex) {
+                        requestCount.abort();
+                        return;
+                    }
+                }
+
+                list.addResponse(response);
+                requestCount.decrement();
+
+                if (i < reqNo) {
+                    conn.requestInput();
+                }
+            }
+
+        };
+
+        NHttpServiceHandler serviceHandler = createHttpServiceHandler(
+                requestHandler,
+                expectationVerifier,
+                this.execService);
+
+        NHttpClientHandler clientHandler = createHttpClientHandler(
+                requestExecutionHandler,
+                this.execService);
+
+        this.server.setRequestCount(requestCount);
+        this.client.setRequestCount(requestCount);
+        
+        this.server.start(serviceHandler);
+        this.client.start(clientHandler);
+
+        ListenerEndpoint endpoint = this.server.getListenerEndpoint();
+        endpoint.waitFor();
+        InetSocketAddress serverAddress = (InetSocketAddress) endpoint.getAddress();
+
+        this.client.openConnection(
+                new InetSocketAddress("localhost", serverAddress.getPort()),
+                responses);
+
+        requestCount.await(10000);
+
+        this.client.shutdown();
+        this.server.shutdown();
+
+        assertEquals(reqNo, responses.size());
+        HttpResponse response = responses.getResponse(0);
+        assertEquals(HttpStatus.SC_EXPECTATION_FAILED, response.getStatusLine().getStatusCode());
+        response = responses.getResponse(1);
+        assertEquals(HttpStatus.SC_EXPECTATION_FAILED, response.getStatusLine().getStatusCode());
+        response = responses.getResponse(2);
+        assertEquals(HttpStatus.SC_OK, response.getStatusLine().getStatusCode());
+    }
+    
+    /**
+     * This test case executes a series of simple (non-pipelined) HEAD requests
+     * over multiple connections.
+     */
+    public void testSimpleHttpHeads() throws Exception {
+
+        final int connNo = 3;
+        final int reqNo = 20;
+        final RequestCount requestCount = new RequestCount(connNo * reqNo * 2);
+
+        final ByteSequence requestData = new ByteSequence();
+        requestData.rnd(reqNo);
+
+        List<ResponseSequence> responseData1 = new ArrayList<ResponseSequence>(connNo);
+        for (int i = 0; i < connNo; i++) {
+            responseData1.add(new ResponseSequence());
+        }
+        List<ResponseSequence> responseData2 = new ArrayList<ResponseSequence>(connNo);
+        for (int i = 0; i < connNo; i++) {
+            responseData2.add(new ResponseSequence());
+        }
+
+        final String[] method = new String[1];
+
+        HttpRequestHandler requestHandler = new HttpRequestHandler() {
+
+            public void handle(
+                    final HttpRequest request,
+                    final HttpResponse response,
+                    final HttpContext context) throws HttpException, IOException {
+
+                String s = request.getRequestLine().getUri();
+                URI uri;
+                try {
+                    uri = new URI(s);
+                } catch (URISyntaxException ex) {
+                    throw new HttpException("Invalid request URI: " + s);
+                }
+                int index = Integer.parseInt(uri.getQuery());
+
+                byte[] data = requestData.getBytes(index);
+                NByteArrayEntity entity = new NByteArrayEntity(data);
+                response.setEntity(entity);
+            }
+
+        };
+
+        HttpRequestExecutionHandler requestExecutionHandler = new HttpRequestExecutionHandler() {
+
+            public void initalizeContext(final HttpContext context, final Object attachment) {
+                context.setAttribute("LIST", (ResponseSequence) attachment);
+                context.setAttribute("REQ-COUNT", new Integer(0));
+                context.setAttribute("RES-COUNT", new Integer(0));
+            }
+
+            public void finalizeContext(final HttpContext context) {
+            }
+
+            public HttpRequest submitRequest(final HttpContext context) {
+                int i = ((Integer) context.getAttribute("REQ-COUNT")).intValue();
+                BasicHttpRequest request = null;
+                if (i < reqNo) {
+                    request = new BasicHttpRequest(method[0], "/?" + i);
+                    context.setAttribute("REQ-COUNT", new Integer(i + 1));
+                }
+                return request;
+            }
+
+            public void handleResponse(final HttpResponse response, final HttpContext context) {
+                NHttpConnection conn = (NHttpConnection) context.getAttribute(
+                        ExecutionContext.HTTP_CONNECTION);
+
+                ResponseSequence list = (ResponseSequence) context.getAttribute("LIST");
+                int i = ((Integer) context.getAttribute("RES-COUNT")).intValue();
+                i++;
+                context.setAttribute("RES-COUNT", new Integer(i));
+
+                list.addResponse(response);
+                requestCount.decrement();
+
+                if (i < reqNo) {
+                    conn.requestInput();
+                }
+            }
+
+        };
+
+        NHttpServiceHandler serviceHandler = createHttpServiceHandler(
+                requestHandler,
+                null,
+                this.execService);
+
+        NHttpClientHandler clientHandler = createHttpClientHandler(
+                requestExecutionHandler,
+                this.execService);
+
+        this.server.setRequestCount(requestCount);
+        this.client.setRequestCount(requestCount);
+        
+        this.server.start(serviceHandler);
+        this.client.start(clientHandler);
+
+        ListenerEndpoint endpoint = this.server.getListenerEndpoint();
+        endpoint.waitFor();
+        InetSocketAddress serverAddress = (InetSocketAddress) endpoint.getAddress();
+
+        method[0] = "GET";
+
+        for (int i = 0; i < responseData1.size(); i++) {
+            this.client.openConnection(
+                    new InetSocketAddress("localhost", serverAddress.getPort()),
+                    responseData1.get(i));
+        }
+
+        requestCount.await(connNo * reqNo, 10000);
+        assertEquals(connNo * reqNo, requestCount.getValue());
+
+        method[0] = "HEAD";
+
+        for (int i = 0; i < responseData2.size(); i++) {
+            this.client.openConnection(
+                    new InetSocketAddress("localhost", serverAddress.getPort()),
+                    responseData2.get(i));
+        }
+
+
+        requestCount.await(10000);
+        assertEquals(0, requestCount.getValue());
+
+        this.client.shutdown();
+        this.server.shutdown();
+
+        for (int c = 0; c < connNo; c++) {
+            ResponseSequence getResponses = responseData1.get(c);
+            ResponseSequence headResponses = responseData2.get(c);
+            ByteSequence expectedPackets = requestData;
+            assertEquals(expectedPackets.size(), headResponses.size());
+            assertEquals(expectedPackets.size(), getResponses.size());
+            for (int p = 0; p < requestData.size(); p++) {
+                HttpResponse getResponse = getResponses.getResponse(p);
+                HttpResponse headResponse = headResponses.getResponse(p);
+                assertEquals(null, headResponse.getEntity());
+
+                Header[] getHeaders = getResponse.getAllHeaders();
+                Header[] headHeaders = headResponse.getAllHeaders();
+                assertEquals(getHeaders.length, headHeaders.length);
+                for (int j = 0; j < getHeaders.length; j++) {
+                    if ("Date".equals(getHeaders[j].getName())) {
+                        continue;
+                    }
+                    assertEquals(getHeaders[j].toString(), headHeaders[j].toString());
+                }
+            }
+        }
+    }
+
 }