0001: /*
0002: * $HeadURL: https://svn.apache.org/repos/asf/httpcomponents/httpcore/tags/4.0-beta1/module-nio/src/test/java/org/apache/http/nio/protocol/TestNIOHttp.java $
0003: * $Revision: 613298 $
0004: * $Date: 2008-01-18 23:09:22 +0100 (Fri, 18 Jan 2008) $
0005: * ====================================================================
0006: * Licensed to the Apache Software Foundation (ASF) under one
0007: * or more contributor license agreements. See the NOTICE file
0008: * distributed with this work for additional information
0009: * regarding copyright ownership. The ASF licenses this file
0010: * to you under the Apache License, Version 2.0 (the
0011: * "License"); you may not use this file except in compliance
0012: * with the License. You may obtain a copy of the License at
0013: *
0014: * http://www.apache.org/licenses/LICENSE-2.0
0015: *
0016: * Unless required by applicable law or agreed to in writing,
0017: * software distributed under the License is distributed on an
0018: * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
0019: * KIND, either express or implied. See the License for the
0020: * specific language governing permissions and limitations
0021: * under the License.
0022: * ====================================================================
0023: *
0024: * This software consists of voluntary contributions made by many
0025: * individuals on behalf of the Apache Software Foundation. For more
0026: * information on the Apache Software Foundation, please see
0027: * <http://www.apache.org/>.
0028: *
0029: */
0030:
0031: package org.apache.http.nio.protocol;
0032:
0033: import java.io.IOException;
0034: import java.net.InetSocketAddress;
0035: import java.net.URI;
0036: import java.net.URISyntaxException;
0037: import java.util.ArrayList;
0038: import java.util.List;
0039:
0040: import junit.framework.Test;
0041: import junit.framework.TestCase;
0042: import junit.framework.TestSuite;
0043:
0044: import org.apache.http.Header;
0045: import org.apache.http.HttpEntity;
0046: import org.apache.http.HttpEntityEnclosingRequest;
0047: import org.apache.http.HttpException;
0048: import org.apache.http.HttpRequest;
0049: import org.apache.http.HttpResponse;
0050: import org.apache.http.HttpStatus;
0051: import org.apache.http.HttpVersion;
0052: import org.apache.http.entity.ByteArrayEntity;
0053: import org.apache.http.entity.StringEntity;
0054: import org.apache.http.impl.DefaultConnectionReuseStrategy;
0055: import org.apache.http.impl.DefaultHttpResponseFactory;
0056: import org.apache.http.message.BasicHttpEntityEnclosingRequest;
0057: import org.apache.http.message.BasicHttpRequest;
0058: import org.apache.http.mockup.ByteSequence;
0059: import org.apache.http.mockup.RequestCount;
0060: import org.apache.http.mockup.ResponseSequence;
0061: import org.apache.http.mockup.SimpleEventListener;
0062: import org.apache.http.mockup.SimpleHttpRequestHandlerResolver;
0063: import org.apache.http.mockup.TestHttpClient;
0064: import org.apache.http.mockup.TestHttpServer;
0065: import org.apache.http.nio.NHttpClientHandler;
0066: import org.apache.http.nio.NHttpConnection;
0067: import org.apache.http.nio.NHttpServiceHandler;
0068: import org.apache.http.nio.reactor.ListenerEndpoint;
0069: import org.apache.http.params.BasicHttpParams;
0070: import org.apache.http.params.CoreConnectionPNames;
0071: import org.apache.http.params.CoreProtocolPNames;
0072: import org.apache.http.params.HttpParams;
0073: import org.apache.http.protocol.BasicHttpProcessor;
0074: import org.apache.http.protocol.ExecutionContext;
0075: import org.apache.http.protocol.HttpContext;
0076: import org.apache.http.protocol.HttpExpectationVerifier;
0077: import org.apache.http.protocol.HttpRequestHandler;
0078: import org.apache.http.protocol.RequestConnControl;
0079: import org.apache.http.protocol.RequestContent;
0080: import org.apache.http.protocol.RequestExpectContinue;
0081: import org.apache.http.protocol.RequestTargetHost;
0082: import org.apache.http.protocol.RequestUserAgent;
0083: import org.apache.http.protocol.ResponseConnControl;
0084: import org.apache.http.protocol.ResponseContent;
0085: import org.apache.http.protocol.ResponseDate;
0086: import org.apache.http.protocol.ResponseServer;
0087: import org.apache.http.util.EncodingUtils;
0088: import org.apache.http.util.EntityUtils;
0089:
0090: /**
0091: * HttpCore NIO integration tests.
0092: *
0093: * @author <a href="mailto:oleg at ural.ru">Oleg Kalnichevski</a>
0094: *
0095: * @version $Id: TestNIOHttp.java 613298 2008-01-18 22:09:22Z sebb $
0096: */
0097: public class TestNIOHttp extends TestCase {
0098:
0099: // ------------------------------------------------------------ Constructor
0100: public TestNIOHttp(String testName) {
0101: super (testName);
0102: }
0103:
0104: // ------------------------------------------------------------------- Main
0105: public static void main(String args[]) {
0106: String[] testCaseName = { TestNIOHttp.class.getName() };
0107: junit.textui.TestRunner.main(testCaseName);
0108: }
0109:
0110: // ------------------------------------------------------- TestCase Methods
0111:
0112: public static Test suite() {
0113: return new TestSuite(TestNIOHttp.class);
0114: }
0115:
0116: private TestHttpServer server;
0117: private TestHttpClient client;
0118:
0119: @Override
0120: protected void setUp() throws Exception {
0121: HttpParams serverParams = new BasicHttpParams();
0122: serverParams.setIntParameter(CoreConnectionPNames.SO_TIMEOUT,
0123: 5000).setIntParameter(
0124: CoreConnectionPNames.SOCKET_BUFFER_SIZE, 8 * 1024)
0125: .setBooleanParameter(
0126: CoreConnectionPNames.STALE_CONNECTION_CHECK,
0127: false).setBooleanParameter(
0128: CoreConnectionPNames.TCP_NODELAY, true)
0129: .setParameter(CoreProtocolPNames.ORIGIN_SERVER,
0130: "TEST-SERVER/1.1");
0131:
0132: this .server = new TestHttpServer(serverParams);
0133:
0134: HttpParams clientParams = new BasicHttpParams();
0135: clientParams.setIntParameter(CoreConnectionPNames.SO_TIMEOUT,
0136: 5000).setIntParameter(
0137: CoreConnectionPNames.CONNECTION_TIMEOUT, 2000)
0138: .setIntParameter(
0139: CoreConnectionPNames.SOCKET_BUFFER_SIZE,
0140: 8 * 1024).setBooleanParameter(
0141: CoreConnectionPNames.STALE_CONNECTION_CHECK,
0142: false).setBooleanParameter(
0143: CoreConnectionPNames.TCP_NODELAY, true)
0144: .setParameter(CoreProtocolPNames.USER_AGENT,
0145: "TEST-CLIENT/1.1");
0146:
0147: this .client = new TestHttpClient(clientParams);
0148: }
0149:
0150: @Override
0151: protected void tearDown() throws Exception {
0152: this .server.shutdown();
0153: this .client.shutdown();
0154: }
0155:
0156: private NHttpServiceHandler createHttpServiceHandler(
0157: final HttpRequestHandler requestHandler,
0158: final HttpExpectationVerifier expectationVerifier) {
0159: BasicHttpProcessor httpproc = new BasicHttpProcessor();
0160: httpproc.addInterceptor(new ResponseDate());
0161: httpproc.addInterceptor(new ResponseServer());
0162: httpproc.addInterceptor(new ResponseContent());
0163: httpproc.addInterceptor(new ResponseConnControl());
0164:
0165: BufferingHttpServiceHandler serviceHandler = new BufferingHttpServiceHandler(
0166: httpproc, new DefaultHttpResponseFactory(),
0167: new DefaultConnectionReuseStrategy(), this .server
0168: .getParams());
0169:
0170: serviceHandler
0171: .setHandlerResolver(new SimpleHttpRequestHandlerResolver(
0172: requestHandler));
0173: serviceHandler.setExpectationVerifier(expectationVerifier);
0174: serviceHandler.setEventListener(new SimpleEventListener());
0175:
0176: return serviceHandler;
0177: }
0178:
0179: private NHttpClientHandler createHttpClientHandler(
0180: final HttpRequestExecutionHandler requestExecutionHandler) {
0181: BasicHttpProcessor httpproc = new BasicHttpProcessor();
0182: httpproc.addInterceptor(new RequestContent());
0183: httpproc.addInterceptor(new RequestTargetHost());
0184: httpproc.addInterceptor(new RequestConnControl());
0185: httpproc.addInterceptor(new RequestUserAgent());
0186: httpproc.addInterceptor(new RequestExpectContinue());
0187:
0188: BufferingHttpClientHandler clientHandler = new BufferingHttpClientHandler(
0189: httpproc, requestExecutionHandler,
0190: new DefaultConnectionReuseStrategy(), this .client
0191: .getParams());
0192:
0193: clientHandler.setEventListener(new SimpleEventListener());
0194: return clientHandler;
0195: }
0196:
0197: /**
0198: * This test case executes a series of simple (non-pipelined) GET requests
0199: * over multiple connections.
0200: */
0201: public void testSimpleHttpGets() throws Exception {
0202:
0203: final int connNo = 3;
0204: final int reqNo = 20;
0205: final RequestCount requestCount = new RequestCount(connNo
0206: * reqNo);
0207: final ByteSequence requestData = new ByteSequence();
0208: requestData.rnd(reqNo);
0209:
0210: List<ByteSequence> responseData = new ArrayList<ByteSequence>(
0211: connNo);
0212: for (int i = 0; i < connNo; i++) {
0213: responseData.add(new ByteSequence());
0214: }
0215:
0216: HttpRequestHandler requestHandler = new HttpRequestHandler() {
0217:
0218: public void handle(final HttpRequest request,
0219: final HttpResponse response,
0220: final HttpContext context) throws HttpException,
0221: IOException {
0222:
0223: String s = request.getRequestLine().getUri();
0224: URI uri;
0225: try {
0226: uri = new URI(s);
0227: } catch (URISyntaxException ex) {
0228: throw new HttpException("Invalid request URI: " + s);
0229: }
0230: int index = Integer.parseInt(uri.getQuery());
0231: byte[] bytes = requestData.getBytes(index);
0232: ByteArrayEntity entity = new ByteArrayEntity(bytes);
0233: response.setEntity(entity);
0234: }
0235:
0236: };
0237:
0238: HttpRequestExecutionHandler requestExecutionHandler = new HttpRequestExecutionHandler() {
0239:
0240: public void initalizeContext(final HttpContext context,
0241: final Object attachment) {
0242: context.setAttribute("LIST", (ByteSequence) attachment);
0243: context.setAttribute("REQ-COUNT", new Integer(0));
0244: context.setAttribute("RES-COUNT", new Integer(0));
0245: }
0246:
0247: public void finalizeContext(final HttpContext context) {
0248: }
0249:
0250: public HttpRequest submitRequest(final HttpContext context) {
0251: int i = ((Integer) context.getAttribute("REQ-COUNT"))
0252: .intValue();
0253: BasicHttpRequest get = null;
0254: if (i < reqNo) {
0255: get = new BasicHttpRequest("GET", "/?" + i);
0256: context.setAttribute("REQ-COUNT",
0257: new Integer(i + 1));
0258: }
0259: return get;
0260: }
0261:
0262: public void handleResponse(final HttpResponse response,
0263: final HttpContext context) {
0264: NHttpConnection conn = (NHttpConnection) context
0265: .getAttribute(ExecutionContext.HTTP_CONNECTION);
0266:
0267: ByteSequence list = (ByteSequence) context
0268: .getAttribute("LIST");
0269: int i = ((Integer) context.getAttribute("RES-COUNT"))
0270: .intValue();
0271: i++;
0272: context.setAttribute("RES-COUNT", new Integer(i));
0273:
0274: try {
0275: HttpEntity entity = response.getEntity();
0276: byte[] data = EntityUtils.toByteArray(entity);
0277: list.addBytes(data);
0278: requestCount.decrement();
0279: } catch (IOException ex) {
0280: requestCount.abort();
0281: return;
0282: }
0283:
0284: if (i < reqNo) {
0285: conn.requestInput();
0286: }
0287: }
0288:
0289: };
0290:
0291: NHttpServiceHandler serviceHandler = createHttpServiceHandler(
0292: requestHandler, null);
0293:
0294: NHttpClientHandler clientHandler = createHttpClientHandler(requestExecutionHandler);
0295:
0296: this .server.start(serviceHandler);
0297: this .client.start(clientHandler);
0298:
0299: ListenerEndpoint endpoint = this .server.getListenerEndpoint();
0300: endpoint.waitFor();
0301: InetSocketAddress serverAddress = (InetSocketAddress) endpoint
0302: .getAddress();
0303:
0304: for (int i = 0; i < responseData.size(); i++) {
0305: this .client.openConnection(new InetSocketAddress(
0306: "localhost", serverAddress.getPort()), responseData
0307: .get(i));
0308: }
0309:
0310: requestCount.await(10000);
0311: assertEquals(0, requestCount.getValue());
0312:
0313: this .client.shutdown();
0314: this .server.shutdown();
0315:
0316: for (int c = 0; c < responseData.size(); c++) {
0317: ByteSequence receivedPackets = responseData.get(c);
0318: ByteSequence expectedPackets = requestData;
0319: assertEquals(expectedPackets.size(), receivedPackets.size());
0320: for (int p = 0; p < requestData.size(); p++) {
0321: byte[] expected = requestData.getBytes(p);
0322: byte[] received = receivedPackets.getBytes(p);
0323:
0324: assertEquals(expected.length, received.length);
0325: for (int i = 0; i < expected.length; i++) {
0326: assertEquals(expected[i], received[i]);
0327: }
0328: }
0329: }
0330:
0331: }
0332:
0333: /**
0334: * This test case executes a series of simple (non-pipelined) POST requests
0335: * with content length delimited content over multiple connections.
0336: */
0337: public void testSimpleHttpPostsWithContentLength() throws Exception {
0338:
0339: final int connNo = 3;
0340: final int reqNo = 20;
0341: final RequestCount requestCount = new RequestCount(connNo
0342: * reqNo);
0343: final ByteSequence requestData = new ByteSequence();
0344: requestData.rnd(reqNo);
0345:
0346: List<ByteSequence> responseData = new ArrayList<ByteSequence>(
0347: connNo);
0348: for (int i = 0; i < connNo; i++) {
0349: responseData.add(new ByteSequence());
0350: }
0351:
0352: HttpRequestHandler requestHandler = new HttpRequestHandler() {
0353:
0354: public void handle(final HttpRequest request,
0355: final HttpResponse response,
0356: final HttpContext context) throws HttpException,
0357: IOException {
0358:
0359: if (request instanceof HttpEntityEnclosingRequest) {
0360: HttpEntity incoming = ((HttpEntityEnclosingRequest) request)
0361: .getEntity();
0362: byte[] data = EntityUtils.toByteArray(incoming);
0363:
0364: ByteArrayEntity outgoing = new ByteArrayEntity(data);
0365: outgoing.setChunked(false);
0366: response.setEntity(outgoing);
0367: } else {
0368: StringEntity outgoing = new StringEntity(
0369: "No content");
0370: response.setEntity(outgoing);
0371: }
0372: }
0373:
0374: };
0375:
0376: HttpRequestExecutionHandler requestExecutionHandler = new HttpRequestExecutionHandler() {
0377:
0378: public void initalizeContext(final HttpContext context,
0379: final Object attachment) {
0380: context.setAttribute("LIST", (ByteSequence) attachment);
0381: context.setAttribute("REQ-COUNT", new Integer(0));
0382: context.setAttribute("RES-COUNT", new Integer(0));
0383: }
0384:
0385: public void finalizeContext(final HttpContext context) {
0386: }
0387:
0388: public HttpRequest submitRequest(final HttpContext context) {
0389: int i = ((Integer) context.getAttribute("REQ-COUNT"))
0390: .intValue();
0391: BasicHttpEntityEnclosingRequest post = null;
0392: if (i < reqNo) {
0393: post = new BasicHttpEntityEnclosingRequest("POST",
0394: "/?" + i);
0395:
0396: byte[] data = requestData.getBytes(i);
0397: ByteArrayEntity outgoing = new ByteArrayEntity(data);
0398: post.setEntity(outgoing);
0399:
0400: context.setAttribute("REQ-COUNT",
0401: new Integer(i + 1));
0402: }
0403: return post;
0404: }
0405:
0406: public void handleResponse(final HttpResponse response,
0407: final HttpContext context) {
0408: NHttpConnection conn = (NHttpConnection) context
0409: .getAttribute(ExecutionContext.HTTP_CONNECTION);
0410:
0411: ByteSequence list = (ByteSequence) context
0412: .getAttribute("LIST");
0413: int i = ((Integer) context.getAttribute("RES-COUNT"))
0414: .intValue();
0415: i++;
0416: context.setAttribute("RES-COUNT", new Integer(i));
0417:
0418: try {
0419: HttpEntity entity = response.getEntity();
0420: byte[] data = EntityUtils.toByteArray(entity);
0421: list.addBytes(data);
0422: requestCount.decrement();
0423: } catch (IOException ex) {
0424: requestCount.abort();
0425: return;
0426: }
0427:
0428: if (i < reqNo) {
0429: conn.requestInput();
0430: }
0431: }
0432:
0433: };
0434:
0435: NHttpServiceHandler serviceHandler = createHttpServiceHandler(
0436: requestHandler, null);
0437:
0438: NHttpClientHandler clientHandler = createHttpClientHandler(requestExecutionHandler);
0439:
0440: this .server.start(serviceHandler);
0441: this .client.start(clientHandler);
0442:
0443: ListenerEndpoint endpoint = this .server.getListenerEndpoint();
0444: endpoint.waitFor();
0445: InetSocketAddress serverAddress = (InetSocketAddress) endpoint
0446: .getAddress();
0447:
0448: for (int i = 0; i < responseData.size(); i++) {
0449: this .client.openConnection(new InetSocketAddress(
0450: "localhost", serverAddress.getPort()), responseData
0451: .get(i));
0452: }
0453:
0454: requestCount.await(10000);
0455: assertEquals(0, requestCount.getValue());
0456:
0457: this .client.shutdown();
0458: this .server.shutdown();
0459:
0460: for (int c = 0; c < responseData.size(); c++) {
0461: ByteSequence receivedPackets = responseData.get(c);
0462: ByteSequence expectedPackets = requestData;
0463: assertEquals(expectedPackets.size(), receivedPackets.size());
0464: for (int p = 0; p < requestData.size(); p++) {
0465: byte[] expected = requestData.getBytes(p);
0466: byte[] received = receivedPackets.getBytes(p);
0467:
0468: assertEquals(expected.length, received.length);
0469: for (int i = 0; i < expected.length; i++) {
0470: assertEquals(expected[i], received[i]);
0471: }
0472: }
0473: }
0474:
0475: }
0476:
0477: /**
0478: * This test case executes a series of simple (non-pipelined) POST requests
0479: * with chunk coded content content over multiple connections.
0480: */
0481: public void testSimpleHttpPostsChunked() throws Exception {
0482:
0483: final int connNo = 3;
0484: final int reqNo = 20;
0485: final RequestCount requestCount = new RequestCount(connNo
0486: * reqNo);
0487: final ByteSequence requestData = new ByteSequence();
0488: requestData.rnd(reqNo);
0489:
0490: List<ByteSequence> responseData = new ArrayList<ByteSequence>(
0491: connNo);
0492: for (int i = 0; i < connNo; i++) {
0493: responseData.add(new ByteSequence());
0494: }
0495:
0496: HttpRequestHandler requestHandler = new HttpRequestHandler() {
0497:
0498: public void handle(final HttpRequest request,
0499: final HttpResponse response,
0500: final HttpContext context) throws HttpException,
0501: IOException {
0502:
0503: if (request instanceof HttpEntityEnclosingRequest) {
0504: HttpEntity incoming = ((HttpEntityEnclosingRequest) request)
0505: .getEntity();
0506: byte[] data = EntityUtils.toByteArray(incoming);
0507: ByteArrayEntity outgoing = new ByteArrayEntity(data);
0508: outgoing.setChunked(true);
0509: response.setEntity(outgoing);
0510: } else {
0511: StringEntity outgoing = new StringEntity(
0512: "No content");
0513: response.setEntity(outgoing);
0514: }
0515: }
0516:
0517: };
0518:
0519: HttpRequestExecutionHandler requestExecutionHandler = new HttpRequestExecutionHandler() {
0520:
0521: public void initalizeContext(final HttpContext context,
0522: final Object attachment) {
0523: context.setAttribute("LIST", (ByteSequence) attachment);
0524: context.setAttribute("REQ-COUNT", new Integer(0));
0525: context.setAttribute("RES-COUNT", new Integer(0));
0526: }
0527:
0528: public void finalizeContext(final HttpContext context) {
0529: }
0530:
0531: public HttpRequest submitRequest(final HttpContext context) {
0532: int i = ((Integer) context.getAttribute("REQ-COUNT"))
0533: .intValue();
0534: BasicHttpEntityEnclosingRequest post = null;
0535: if (i < reqNo) {
0536: post = new BasicHttpEntityEnclosingRequest("POST",
0537: "/?" + i);
0538: byte[] data = requestData.getBytes(i);
0539: ByteArrayEntity outgoing = new ByteArrayEntity(data);
0540: outgoing.setChunked(true);
0541: post.setEntity(outgoing);
0542:
0543: context.setAttribute("REQ-COUNT",
0544: new Integer(i + 1));
0545: }
0546: return post;
0547: }
0548:
0549: public void handleResponse(final HttpResponse response,
0550: final HttpContext context) {
0551: NHttpConnection conn = (NHttpConnection) context
0552: .getAttribute(ExecutionContext.HTTP_CONNECTION);
0553:
0554: ByteSequence list = (ByteSequence) context
0555: .getAttribute("LIST");
0556: int i = ((Integer) context.getAttribute("RES-COUNT"))
0557: .intValue();
0558: i++;
0559: context.setAttribute("RES-COUNT", new Integer(i));
0560:
0561: try {
0562: HttpEntity entity = response.getEntity();
0563: byte[] data = EntityUtils.toByteArray(entity);
0564: list.addBytes(data);
0565: requestCount.decrement();
0566: } catch (IOException ex) {
0567: requestCount.abort();
0568: return;
0569: }
0570:
0571: if (i < reqNo) {
0572: conn.requestInput();
0573: }
0574: }
0575:
0576: };
0577:
0578: NHttpServiceHandler serviceHandler = createHttpServiceHandler(
0579: requestHandler, null);
0580:
0581: NHttpClientHandler clientHandler = createHttpClientHandler(requestExecutionHandler);
0582:
0583: this .server.start(serviceHandler);
0584: this .client.start(clientHandler);
0585:
0586: ListenerEndpoint endpoint = this .server.getListenerEndpoint();
0587: endpoint.waitFor();
0588: InetSocketAddress serverAddress = (InetSocketAddress) endpoint
0589: .getAddress();
0590:
0591: for (int i = 0; i < responseData.size(); i++) {
0592: this .client.openConnection(new InetSocketAddress(
0593: "localhost", serverAddress.getPort()), responseData
0594: .get(i));
0595: }
0596:
0597: requestCount.await(10000);
0598: if (requestCount.isAborted()) {
0599: System.out.println("Test case aborted");
0600: }
0601: assertEquals(0, requestCount.getValue());
0602:
0603: this .client.shutdown();
0604: this .server.shutdown();
0605:
0606: for (int c = 0; c < responseData.size(); c++) {
0607: ByteSequence receivedPackets = responseData.get(c);
0608: ByteSequence expectedPackets = requestData;
0609: assertEquals(expectedPackets.size(), receivedPackets.size());
0610: for (int p = 0; p < requestData.size(); p++) {
0611: byte[] expected = requestData.getBytes(p);
0612: byte[] received = receivedPackets.getBytes(p);
0613:
0614: assertEquals(expected.length, received.length);
0615: for (int i = 0; i < expected.length; i++) {
0616: assertEquals(expected[i], received[i]);
0617: }
0618: }
0619: }
0620:
0621: }
0622:
0623: /**
0624: * This test case executes a series of simple (non-pipelined) HTTP/1.0
0625: * POST requests over multiple persistent connections.
0626: */
0627: public void testSimpleHttpPostsHTTP10() throws Exception {
0628:
0629: final int connNo = 3;
0630: final int reqNo = 20;
0631: final RequestCount requestCount = new RequestCount(connNo
0632: * reqNo);
0633: final ByteSequence requestData = new ByteSequence();
0634: requestData.rnd(reqNo);
0635:
0636: List<ByteSequence> responseData = new ArrayList<ByteSequence>(
0637: connNo);
0638: for (int i = 0; i < connNo; i++) {
0639: responseData.add(new ByteSequence());
0640: }
0641:
0642: HttpRequestHandler requestHandler = new HttpRequestHandler() {
0643:
0644: public void handle(final HttpRequest request,
0645: final HttpResponse response,
0646: final HttpContext context) throws HttpException,
0647: IOException {
0648:
0649: if (request instanceof HttpEntityEnclosingRequest) {
0650: HttpEntity incoming = ((HttpEntityEnclosingRequest) request)
0651: .getEntity();
0652: byte[] data = EntityUtils.toByteArray(incoming);
0653:
0654: ByteArrayEntity outgoing = new ByteArrayEntity(data);
0655: outgoing.setChunked(false);
0656: response.setEntity(outgoing);
0657: } else {
0658: StringEntity outgoing = new StringEntity(
0659: "No content");
0660: response.setEntity(outgoing);
0661: }
0662: }
0663:
0664: };
0665:
0666: // Set protocol level to HTTP/1.0
0667: this .client.getParams().setParameter(
0668: CoreProtocolPNames.PROTOCOL_VERSION,
0669: HttpVersion.HTTP_1_0);
0670:
0671: HttpRequestExecutionHandler requestExecutionHandler = new HttpRequestExecutionHandler() {
0672:
0673: public void initalizeContext(final HttpContext context,
0674: final Object attachment) {
0675: context.setAttribute("LIST", (ByteSequence) attachment);
0676: context.setAttribute("REQ-COUNT", new Integer(0));
0677: context.setAttribute("RES-COUNT", new Integer(0));
0678: }
0679:
0680: public void finalizeContext(final HttpContext context) {
0681: }
0682:
0683: public HttpRequest submitRequest(final HttpContext context) {
0684: int i = ((Integer) context.getAttribute("REQ-COUNT"))
0685: .intValue();
0686: BasicHttpEntityEnclosingRequest post = null;
0687: if (i < reqNo) {
0688: post = new BasicHttpEntityEnclosingRequest("POST",
0689: "/?" + i);
0690: byte[] data = requestData.getBytes(i);
0691: ByteArrayEntity outgoing = new ByteArrayEntity(data);
0692: post.setEntity(outgoing);
0693:
0694: context.setAttribute("REQ-COUNT",
0695: new Integer(i + 1));
0696: }
0697: return post;
0698: }
0699:
0700: public void handleResponse(final HttpResponse response,
0701: final HttpContext context) {
0702: NHttpConnection conn = (NHttpConnection) context
0703: .getAttribute(ExecutionContext.HTTP_CONNECTION);
0704:
0705: ByteSequence list = (ByteSequence) context
0706: .getAttribute("LIST");
0707: int i = ((Integer) context.getAttribute("RES-COUNT"))
0708: .intValue();
0709: i++;
0710: context.setAttribute("RES-COUNT", new Integer(i));
0711:
0712: try {
0713: HttpEntity entity = response.getEntity();
0714: byte[] data = EntityUtils.toByteArray(entity);
0715: list.addBytes(data);
0716: requestCount.decrement();
0717: } catch (IOException ex) {
0718: requestCount.abort();
0719: return;
0720: }
0721:
0722: if (i < reqNo) {
0723: conn.requestInput();
0724: }
0725: }
0726:
0727: };
0728:
0729: NHttpServiceHandler serviceHandler = createHttpServiceHandler(
0730: requestHandler, null);
0731:
0732: NHttpClientHandler clientHandler = createHttpClientHandler(requestExecutionHandler);
0733:
0734: this .server.start(serviceHandler);
0735: this .client.start(clientHandler);
0736:
0737: ListenerEndpoint endpoint = this .server.getListenerEndpoint();
0738: endpoint.waitFor();
0739: InetSocketAddress serverAddress = (InetSocketAddress) endpoint
0740: .getAddress();
0741:
0742: for (int i = 0; i < responseData.size(); i++) {
0743: this .client.openConnection(new InetSocketAddress(
0744: "localhost", serverAddress.getPort()), responseData
0745: .get(i));
0746: }
0747:
0748: requestCount.await(10000);
0749: assertEquals(0, requestCount.getValue());
0750:
0751: this .client.shutdown();
0752: this .server.shutdown();
0753:
0754: for (int c = 0; c < responseData.size(); c++) {
0755: ByteSequence receivedPackets = responseData.get(c);
0756: ByteSequence expectedPackets = requestData;
0757: assertEquals(expectedPackets.size(), receivedPackets.size());
0758: for (int p = 0; p < requestData.size(); p++) {
0759: byte[] expected = requestData.getBytes(p);
0760: byte[] received = receivedPackets.getBytes(p);
0761:
0762: assertEquals(expected.length, received.length);
0763: for (int i = 0; i < expected.length; i++) {
0764: assertEquals(expected[i], received[i]);
0765: }
0766: }
0767: }
0768:
0769: }
0770:
0771: /**
0772: * This test case executes a series of simple (non-pipelined) POST requests
0773: * over multiple connections using the 'expect: continue' handshake.
0774: */
0775: public void testHttpPostsWithExpectContinue() throws Exception {
0776:
0777: final int connNo = 3;
0778: final int reqNo = 20;
0779: final RequestCount requestCount = new RequestCount(connNo
0780: * reqNo);
0781: final ByteSequence requestData = new ByteSequence();
0782: requestData.rnd(reqNo);
0783:
0784: List<ByteSequence> responseData = new ArrayList<ByteSequence>(
0785: connNo);
0786: for (int i = 0; i < connNo; i++) {
0787: responseData.add(new ByteSequence());
0788: }
0789:
0790: HttpRequestHandler requestHandler = new HttpRequestHandler() {
0791:
0792: public void handle(final HttpRequest request,
0793: final HttpResponse response,
0794: final HttpContext context) throws HttpException,
0795: IOException {
0796:
0797: if (request instanceof HttpEntityEnclosingRequest) {
0798: HttpEntity incoming = ((HttpEntityEnclosingRequest) request)
0799: .getEntity();
0800: byte[] data = EntityUtils.toByteArray(incoming);
0801: ByteArrayEntity outgoing = new ByteArrayEntity(data);
0802: outgoing.setChunked(true);
0803: response.setEntity(outgoing);
0804: } else {
0805: StringEntity outgoing = new StringEntity(
0806: "No content");
0807: response.setEntity(outgoing);
0808: }
0809: }
0810:
0811: };
0812:
0813: // Activate 'expect: continue' handshake
0814: this .client.getParams().setBooleanParameter(
0815: CoreProtocolPNames.USE_EXPECT_CONTINUE, true);
0816:
0817: HttpRequestExecutionHandler requestExecutionHandler = new HttpRequestExecutionHandler() {
0818:
0819: public void initalizeContext(final HttpContext context,
0820: final Object attachment) {
0821: context.setAttribute("LIST", (ByteSequence) attachment);
0822: context.setAttribute("REQ-COUNT", new Integer(0));
0823: context.setAttribute("RES-COUNT", new Integer(0));
0824: }
0825:
0826: public void finalizeContext(final HttpContext context) {
0827: }
0828:
0829: public HttpRequest submitRequest(final HttpContext context) {
0830: int i = ((Integer) context.getAttribute("REQ-COUNT"))
0831: .intValue();
0832: BasicHttpEntityEnclosingRequest post = null;
0833: if (i < reqNo) {
0834: post = new BasicHttpEntityEnclosingRequest("POST",
0835: "/?" + i);
0836: byte[] data = requestData.getBytes(i);
0837: ByteArrayEntity outgoing = new ByteArrayEntity(data);
0838: outgoing.setChunked(true);
0839: post.setEntity(outgoing);
0840:
0841: context.setAttribute("REQ-COUNT",
0842: new Integer(i + 1));
0843: }
0844: return post;
0845: }
0846:
0847: public void handleResponse(final HttpResponse response,
0848: final HttpContext context) {
0849: NHttpConnection conn = (NHttpConnection) context
0850: .getAttribute(ExecutionContext.HTTP_CONNECTION);
0851:
0852: ByteSequence list = (ByteSequence) context
0853: .getAttribute("LIST");
0854: int i = ((Integer) context.getAttribute("RES-COUNT"))
0855: .intValue();
0856: i++;
0857: context.setAttribute("RES-COUNT", new Integer(i));
0858:
0859: try {
0860: HttpEntity entity = response.getEntity();
0861: byte[] data = EntityUtils.toByteArray(entity);
0862: list.addBytes(data);
0863: requestCount.decrement();
0864: } catch (IOException ex) {
0865: requestCount.abort();
0866: return;
0867: }
0868:
0869: if (i < reqNo) {
0870: conn.requestInput();
0871: }
0872: }
0873:
0874: };
0875:
0876: NHttpServiceHandler serviceHandler = createHttpServiceHandler(
0877: requestHandler, null);
0878:
0879: NHttpClientHandler clientHandler = createHttpClientHandler(requestExecutionHandler);
0880:
0881: this .server.start(serviceHandler);
0882: this .client.start(clientHandler);
0883:
0884: ListenerEndpoint endpoint = this .server.getListenerEndpoint();
0885: endpoint.waitFor();
0886: InetSocketAddress serverAddress = (InetSocketAddress) endpoint
0887: .getAddress();
0888:
0889: for (int i = 0; i < responseData.size(); i++) {
0890: this .client.openConnection(new InetSocketAddress(
0891: "localhost", serverAddress.getPort()), responseData
0892: .get(i));
0893: }
0894:
0895: requestCount.await(10000);
0896: assertEquals(0, requestCount.getValue());
0897:
0898: this .client.shutdown();
0899: this .server.shutdown();
0900:
0901: for (int c = 0; c < responseData.size(); c++) {
0902: ByteSequence receivedPackets = responseData.get(c);
0903: ByteSequence expectedPackets = requestData;
0904: assertEquals(expectedPackets.size(), receivedPackets.size());
0905: for (int p = 0; p < requestData.size(); p++) {
0906: byte[] expected = requestData.getBytes(p);
0907: byte[] received = receivedPackets.getBytes(p);
0908:
0909: assertEquals(expected.length, received.length);
0910: for (int i = 0; i < expected.length; i++) {
0911: assertEquals(expected[i], received[i]);
0912: }
0913: }
0914: }
0915:
0916: }
0917:
0918: /**
0919: * This test case executes a series of simple (non-pipelined) POST requests
0920: * over multiple connections that do not meet the target server expectations.
0921: */
0922: public void testHttpPostsWithExpectationVerification()
0923: throws Exception {
0924:
0925: final int reqNo = 3;
0926: final RequestCount requestCount = new RequestCount(reqNo);
0927: final ResponseSequence responses = new ResponseSequence();
0928:
0929: HttpRequestHandler requestHandler = new HttpRequestHandler() {
0930:
0931: public void handle(final HttpRequest request,
0932: final HttpResponse response,
0933: final HttpContext context) throws HttpException,
0934: IOException {
0935:
0936: StringEntity outgoing = new StringEntity("No content");
0937: response.setEntity(outgoing);
0938: }
0939:
0940: };
0941:
0942: HttpExpectationVerifier expectationVerifier = new HttpExpectationVerifier() {
0943:
0944: public void verify(final HttpRequest request,
0945: final HttpResponse response,
0946: final HttpContext context) throws HttpException {
0947: Header someheader = request.getFirstHeader("Secret");
0948: if (someheader != null) {
0949: int secretNumber;
0950: try {
0951: secretNumber = Integer.parseInt(someheader
0952: .getValue());
0953: } catch (NumberFormatException ex) {
0954: response
0955: .setStatusCode(HttpStatus.SC_BAD_REQUEST);
0956: return;
0957: }
0958: if (secretNumber < 2) {
0959: response
0960: .setStatusCode(HttpStatus.SC_EXPECTATION_FAILED);
0961: ByteArrayEntity outgoing = new ByteArrayEntity(
0962: EncodingUtils
0963: .getAsciiBytes("Wrong secret number"));
0964: response.setEntity(outgoing);
0965: }
0966: }
0967: }
0968:
0969: };
0970:
0971: // Activate 'expect: continue' handshake
0972: this .client.getParams().setBooleanParameter(
0973: CoreProtocolPNames.USE_EXPECT_CONTINUE, true);
0974:
0975: HttpRequestExecutionHandler requestExecutionHandler = new HttpRequestExecutionHandler() {
0976:
0977: public void initalizeContext(final HttpContext context,
0978: final Object attachment) {
0979: context.setAttribute("LIST",
0980: (ResponseSequence) attachment);
0981: context.setAttribute("REQ-COUNT", new Integer(0));
0982: context.setAttribute("RES-COUNT", new Integer(0));
0983: }
0984:
0985: public void finalizeContext(final HttpContext context) {
0986: }
0987:
0988: public HttpRequest submitRequest(final HttpContext context) {
0989: int i = ((Integer) context.getAttribute("REQ-COUNT"))
0990: .intValue();
0991: BasicHttpEntityEnclosingRequest post = null;
0992: if (i < reqNo) {
0993: post = new BasicHttpEntityEnclosingRequest("POST",
0994: "/");
0995: post.addHeader("Secret", Integer.toString(i));
0996: ByteArrayEntity outgoing = new ByteArrayEntity(
0997: EncodingUtils.getAsciiBytes("No content"));
0998: post.setEntity(outgoing);
0999:
1000: context.setAttribute("REQ-COUNT",
1001: new Integer(i + 1));
1002: }
1003: return post;
1004: }
1005:
1006: public void handleResponse(final HttpResponse response,
1007: final HttpContext context) {
1008: NHttpConnection conn = (NHttpConnection) context
1009: .getAttribute(ExecutionContext.HTTP_CONNECTION);
1010:
1011: ResponseSequence list = (ResponseSequence) context
1012: .getAttribute("LIST");
1013: int i = ((Integer) context.getAttribute("RES-COUNT"))
1014: .intValue();
1015: i++;
1016: context.setAttribute("RES-COUNT", new Integer(i));
1017:
1018: HttpEntity entity = response.getEntity();
1019: if (entity != null) {
1020: try {
1021: entity.consumeContent();
1022: } catch (IOException ex) {
1023: requestCount.abort();
1024: return;
1025: }
1026: }
1027:
1028: list.addResponse(response);
1029: requestCount.decrement();
1030:
1031: if (i < reqNo) {
1032: conn.requestInput();
1033: }
1034: }
1035:
1036: };
1037:
1038: NHttpServiceHandler serviceHandler = createHttpServiceHandler(
1039: requestHandler, expectationVerifier);
1040:
1041: NHttpClientHandler clientHandler = createHttpClientHandler(requestExecutionHandler);
1042:
1043: this .server.start(serviceHandler);
1044: this .client.start(clientHandler);
1045:
1046: ListenerEndpoint endpoint = this .server.getListenerEndpoint();
1047: endpoint.waitFor();
1048: InetSocketAddress serverAddress = (InetSocketAddress) endpoint
1049: .getAddress();
1050:
1051: this .client.openConnection(new InetSocketAddress("localhost",
1052: serverAddress.getPort()), responses);
1053:
1054: requestCount.await(1000);
1055:
1056: this .client.shutdown();
1057: this .server.shutdown();
1058:
1059: assertEquals(reqNo, responses.size());
1060: HttpResponse response = responses.getResponse(0);
1061: assertEquals(HttpStatus.SC_EXPECTATION_FAILED, response
1062: .getStatusLine().getStatusCode());
1063: response = responses.getResponse(1);
1064: assertEquals(HttpStatus.SC_EXPECTATION_FAILED, response
1065: .getStatusLine().getStatusCode());
1066: response = responses.getResponse(2);
1067: assertEquals(HttpStatus.SC_OK, response.getStatusLine()
1068: .getStatusCode());
1069: }
1070:
1071: /**
1072: * This test case executes a series of simple (non-pipelined) HEAD requests
1073: * over multiple connections.
1074: */
1075: public void testSimpleHttpHeads() throws Exception {
1076:
1077: final int connNo = 3;
1078: final int reqNo = 20;
1079: final RequestCount requestCount = new RequestCount(connNo
1080: * reqNo * 2);
1081:
1082: final ByteSequence requestData = new ByteSequence();
1083: requestData.rnd(reqNo);
1084:
1085: List<ResponseSequence> responseData1 = new ArrayList<ResponseSequence>(
1086: connNo);
1087: for (int i = 0; i < connNo; i++) {
1088: responseData1.add(new ResponseSequence());
1089: }
1090: List<ResponseSequence> responseData2 = new ArrayList<ResponseSequence>(
1091: connNo);
1092: for (int i = 0; i < connNo; i++) {
1093: responseData2.add(new ResponseSequence());
1094: }
1095:
1096: final String[] method = new String[1];
1097:
1098: HttpRequestHandler requestHandler = new HttpRequestHandler() {
1099:
1100: public void handle(final HttpRequest request,
1101: final HttpResponse response,
1102: final HttpContext context) throws HttpException,
1103: IOException {
1104:
1105: String s = request.getRequestLine().getUri();
1106: URI uri;
1107: try {
1108: uri = new URI(s);
1109: } catch (URISyntaxException ex) {
1110: throw new HttpException("Invalid request URI: " + s);
1111: }
1112: int index = Integer.parseInt(uri.getQuery());
1113:
1114: byte[] data = requestData.getBytes(index);
1115: ByteArrayEntity entity = new ByteArrayEntity(data);
1116: response.setEntity(entity);
1117: }
1118:
1119: };
1120:
1121: HttpRequestExecutionHandler requestExecutionHandler = new HttpRequestExecutionHandler() {
1122:
1123: public void initalizeContext(final HttpContext context,
1124: final Object attachment) {
1125: context.setAttribute("LIST",
1126: (ResponseSequence) attachment);
1127: context.setAttribute("REQ-COUNT", new Integer(0));
1128: context.setAttribute("RES-COUNT", new Integer(0));
1129: }
1130:
1131: public void finalizeContext(final HttpContext context) {
1132: }
1133:
1134: public HttpRequest submitRequest(final HttpContext context) {
1135: int i = ((Integer) context.getAttribute("REQ-COUNT"))
1136: .intValue();
1137: BasicHttpRequest request = null;
1138: if (i < reqNo) {
1139: request = new BasicHttpRequest(method[0], "/?" + i);
1140: context.setAttribute("REQ-COUNT",
1141: new Integer(i + 1));
1142: }
1143: return request;
1144: }
1145:
1146: public void handleResponse(final HttpResponse response,
1147: final HttpContext context) {
1148: NHttpConnection conn = (NHttpConnection) context
1149: .getAttribute(ExecutionContext.HTTP_CONNECTION);
1150:
1151: ResponseSequence list = (ResponseSequence) context
1152: .getAttribute("LIST");
1153: int i = ((Integer) context.getAttribute("RES-COUNT"))
1154: .intValue();
1155: i++;
1156: context.setAttribute("RES-COUNT", new Integer(i));
1157:
1158: list.addResponse(response);
1159: requestCount.decrement();
1160:
1161: if (i < reqNo) {
1162: conn.requestInput();
1163: }
1164: }
1165:
1166: };
1167:
1168: NHttpServiceHandler serviceHandler = createHttpServiceHandler(
1169: requestHandler, null);
1170:
1171: NHttpClientHandler clientHandler = createHttpClientHandler(requestExecutionHandler);
1172:
1173: this .server.start(serviceHandler);
1174: this .client.start(clientHandler);
1175:
1176: ListenerEndpoint endpoint = this .server.getListenerEndpoint();
1177: endpoint.waitFor();
1178: InetSocketAddress serverAddress = (InetSocketAddress) endpoint
1179: .getAddress();
1180:
1181: method[0] = "GET";
1182:
1183: for (int i = 0; i < responseData1.size(); i++) {
1184: this .client.openConnection(new InetSocketAddress(
1185: "localhost", serverAddress.getPort()),
1186: responseData1.get(i));
1187: }
1188:
1189: requestCount.await(connNo * reqNo, 10000);
1190: assertEquals(connNo * reqNo, requestCount.getValue());
1191:
1192: method[0] = "HEAD";
1193:
1194: for (int i = 0; i < responseData2.size(); i++) {
1195: this .client.openConnection(new InetSocketAddress(
1196: "localhost", serverAddress.getPort()),
1197: responseData2.get(i));
1198: }
1199:
1200: requestCount.await(10000);
1201: assertEquals(0, requestCount.getValue());
1202:
1203: this .client.shutdown();
1204: this .server.shutdown();
1205:
1206: for (int c = 0; c < connNo; c++) {
1207: ResponseSequence getResponses = responseData1.get(c);
1208: ResponseSequence headResponses = responseData2.get(c);
1209: ByteSequence expectedPackets = requestData;
1210: assertEquals(expectedPackets.size(), headResponses.size());
1211: assertEquals(expectedPackets.size(), getResponses.size());
1212: for (int p = 0; p < requestData.size(); p++) {
1213: HttpResponse getResponse = getResponses.getResponse(p);
1214: HttpResponse headResponse = headResponses
1215: .getResponse(p);
1216: assertEquals(null, headResponse.getEntity());
1217:
1218: Header[] getHeaders = getResponse.getAllHeaders();
1219: Header[] headHeaders = headResponse.getAllHeaders();
1220: assertEquals(getHeaders.length, headHeaders.length);
1221: for (int j = 0; j < getHeaders.length; j++) {
1222: if ("Date".equals(getHeaders[j].getName())) {
1223: continue;
1224: }
1225: assertEquals(getHeaders[j].toString(),
1226: headHeaders[j].toString());
1227: }
1228: }
1229: }
1230: }
1231:
1232: }
|