View Javadoc
1   /*
2    * ====================================================================
3    * Licensed to the Apache Software Foundation (ASF) under one
4    * or more contributor license agreements.  See the NOTICE file
5    * distributed with this work for additional information
6    * regarding copyright ownership.  The ASF licenses this file
7    * to you under the Apache License, Version 2.0 (the
8    * "License"); you may not use this file except in compliance
9    * with the License.  You may obtain a copy of the License at
10   *
11   *   http://www.apache.org/licenses/LICENSE-2.0
12   *
13   * Unless required by applicable law or agreed to in writing,
14   * software distributed under the License is distributed on an
15   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16   * KIND, either express or implied.  See the License for the
17   * specific language governing permissions and limitations
18   * under the License.
19   * ====================================================================
20   *
21   * This software consists of voluntary contributions made by many
22   * individuals on behalf of the Apache Software Foundation.  For more
23   * information on the Apache Software Foundation, please see
24   * <http://www.apache.org/>.
25   *
26   */
27  
28  package org.apache.http.nio.integration;
29  
30  import java.io.IOException;
31  import java.net.InetSocketAddress;
32  import java.util.Arrays;
33  import java.util.Collection;
34  import java.util.Queue;
35  import java.util.concurrent.ConcurrentLinkedQueue;
36  import java.util.concurrent.Future;
37  
38  import org.apache.http.HttpException;
39  import org.apache.http.HttpHost;
40  import org.apache.http.HttpRequest;
41  import org.apache.http.HttpRequestInterceptor;
42  import org.apache.http.HttpResponse;
43  import org.apache.http.HttpStatus;
44  import org.apache.http.HttpVersion;
45  import org.apache.http.ProtocolVersion;
46  import org.apache.http.entity.ContentType;
47  import org.apache.http.message.BasicHttpEntityEnclosingRequest;
48  import org.apache.http.message.BasicHttpRequest;
49  import org.apache.http.message.BasicHttpResponse;
50  import org.apache.http.nio.entity.NStringEntity;
51  import org.apache.http.nio.protocol.BasicAsyncRequestConsumer;
52  import org.apache.http.nio.protocol.BasicAsyncRequestHandler;
53  import org.apache.http.nio.protocol.BasicAsyncResponseProducer;
54  import org.apache.http.nio.protocol.HttpAsyncExchange;
55  import org.apache.http.nio.protocol.HttpAsyncExpectationVerifier;
56  import org.apache.http.nio.protocol.HttpAsyncRequestConsumer;
57  import org.apache.http.nio.protocol.HttpAsyncRequestHandler;
58  import org.apache.http.nio.reactor.ListenerEndpoint;
59  import org.apache.http.nio.testserver.HttpCoreNIOTestBase;
60  import org.apache.http.protocol.BasicHttpContext;
61  import org.apache.http.protocol.HTTP;
62  import org.apache.http.protocol.HttpContext;
63  import org.apache.http.protocol.HttpRequestHandler;
64  import org.apache.http.protocol.ImmutableHttpProcessor;
65  import org.apache.http.protocol.RequestConnControl;
66  import org.apache.http.protocol.RequestExpectContinue;
67  import org.apache.http.protocol.RequestTargetHost;
68  import org.apache.http.protocol.RequestUserAgent;
69  import org.apache.http.util.EntityUtils;
70  import org.junit.After;
71  import org.junit.Assert;
72  import org.junit.Before;
73  import org.junit.Test;
74  import org.junit.runner.RunWith;
75  import org.junit.runners.Parameterized;
76  
77  /**
78   * HttpCore NIO integration tests for async handlers.
79   */
80  @RunWith(Parameterized.class)
81  public class TestHttpAsyncHandlers extends HttpCoreNIOTestBase {
82  
83      @Parameterized.Parameters(name = "{0}")
84      public static Collection<Object[]> protocols() {
85          return Arrays.asList(new Object[][]{
86                  { ProtocolScheme.http },
87                  { ProtocolScheme.https },
88          });
89      }
90  
91      public TestHttpAsyncHandlers(final ProtocolScheme scheme) {
92          super(scheme);
93      }
94  
95      @Before
96      public void setUp() throws Exception {
97          initServer();
98          initClient();
99      }
100 
101     @After
102     public void tearDown() throws Exception {
103         shutDownClient();
104         shutDownServer();
105     }
106 
107     private HttpHost start() throws IOException, InterruptedException {
108         this.server.start();
109         this.client.start();
110 
111         final ListenerEndpoint endpoint = this.server.getListenerEndpoint();
112         endpoint.waitFor();
113 
114         final InetSocketAddress address = (InetSocketAddress) endpoint.getAddress();
115         return new HttpHost("localhost", address.getPort(), getScheme().name());
116     }
117 
118     private static String createRequestUri(final String pattern, final int count) {
119         return pattern + "x" + count;
120     }
121 
122     private static String createExpectedString(final String pattern, final int count) {
123         final StringBuilder buffer = new StringBuilder();
124         for (int i = 0; i < count; i++) {
125             buffer.append(pattern);
126         }
127         return buffer.toString();
128     }
129 
130     @Test
131     public void testHttpGets() throws Exception {
132         this.server.registerHandler("*", new BasicAsyncRequestHandler(new SimpleRequestHandler()));
133         final HttpHost target = start();
134 
135         this.client.setMaxPerRoute(3);
136         this.client.setMaxTotal(3);
137 
138         final String pattern = RndTestPatternGenerator.generateText();
139         final int count = RndTestPatternGenerator.generateCount(1000);
140 
141         final String expectedPattern = createExpectedString(pattern, count);
142 
143         final Queue<Future<HttpResponse>> queue = new ConcurrentLinkedQueue<Future<HttpResponse>>();
144         for (int i = 0; i < 30; i++) {
145             final BasicHttpRequest request = new BasicHttpRequest("GET", createRequestUri(pattern, count));
146             final Future<HttpResponse> future = this.client.execute(target, request);
147             queue.add(future);
148         }
149 
150         while (!queue.isEmpty()) {
151             final Future<HttpResponse> future = queue.remove();
152             final HttpResponse response = future.get();
153             Assert.assertNotNull(response);
154             Assert.assertEquals(expectedPattern, EntityUtils.toString(response.getEntity()));
155         }
156     }
157 
158     @Test
159     public void testHttpHeads() throws Exception {
160         this.server.registerHandler("*", new BasicAsyncRequestHandler(new SimpleRequestHandler()));
161         final HttpHost target = start();
162 
163         this.client.setMaxPerRoute(3);
164         this.client.setMaxTotal(3);
165 
166         final String pattern = RndTestPatternGenerator.generateText();
167         final int count = RndTestPatternGenerator.generateCount(1000);
168 
169         final Queue<Future<HttpResponse>> queue = new ConcurrentLinkedQueue<Future<HttpResponse>>();
170         for (int i = 0; i < 30; i++) {
171             final BasicHttpRequest request = new BasicHttpRequest("HEAD", createRequestUri(pattern, count));
172             final Future<HttpResponse> future = this.client.execute(target, request);
173             queue.add(future);
174         }
175 
176         while (!queue.isEmpty()) {
177             final Future<HttpResponse> future = queue.remove();
178             final HttpResponse response = future.get();
179             Assert.assertNotNull(response);
180             Assert.assertEquals(HttpStatus.SC_OK, response.getStatusLine().getStatusCode());
181         }
182     }
183 
184     @Test
185     public void testHttpPostsWithContentLength() throws Exception {
186         this.server.registerHandler("*", new BasicAsyncRequestHandler(new SimpleRequestHandler()));
187         final HttpHost target = start();
188 
189         this.client.setMaxPerRoute(3);
190         this.client.setMaxTotal(3);
191 
192         final String pattern = RndTestPatternGenerator.generateText();
193         final int count = RndTestPatternGenerator.generateCount(1000);
194 
195         final String expectedPattern = createExpectedString(pattern, count);
196 
197         final Queue<Future<HttpResponse>> queue = new ConcurrentLinkedQueue<Future<HttpResponse>>();
198         for (int i = 0; i < 30; i++) {
199             final BasicHttpEntityEnclosingRequest request = new BasicHttpEntityEnclosingRequest(
200                     "POST", createRequestUri(pattern, count));
201             final NStringEntity entity = new NStringEntity(expectedPattern, ContentType.DEFAULT_TEXT);
202             request.setEntity(entity);
203             final Future<HttpResponse> future = this.client.execute(target, request);
204             queue.add(future);
205         }
206 
207         while (!queue.isEmpty()) {
208             final Future<HttpResponse> future = queue.remove();
209             final HttpResponse response = future.get();
210             Assert.assertNotNull(response);
211             Assert.assertEquals(expectedPattern, EntityUtils.toString(response.getEntity()));
212         }
213     }
214 
215     @Test
216     public void testHttpPostsChunked() throws Exception {
217         this.server.registerHandler("*", new BasicAsyncRequestHandler(new SimpleRequestHandler()));
218         final HttpHost target = start();
219 
220         this.client.setMaxPerRoute(3);
221         this.client.setMaxTotal(3);
222 
223         final String pattern = RndTestPatternGenerator.generateText();
224         final int count = RndTestPatternGenerator.generateCount(1000);
225 
226         final String expectedPattern = createExpectedString(pattern, count);
227 
228         final Queue<Future<HttpResponse>> queue = new ConcurrentLinkedQueue<Future<HttpResponse>>();
229         for (int i = 0; i < 30; i++) {
230             final BasicHttpEntityEnclosingRequest request = new BasicHttpEntityEnclosingRequest(
231                     "POST", createRequestUri(pattern, count));
232             final NStringEntity entity = new NStringEntity(expectedPattern, ContentType.DEFAULT_TEXT);
233             entity.setChunked(true);
234             request.setEntity(entity);
235             final Future<HttpResponse> future = this.client.execute(target, request);
236             queue.add(future);
237         }
238 
239         while (!queue.isEmpty()) {
240             final Future<HttpResponse> future = queue.remove();
241             final HttpResponse response = future.get();
242             Assert.assertNotNull(response);
243             Assert.assertEquals(expectedPattern, EntityUtils.toString(response.getEntity()));
244         }
245     }
246 
247     @Test
248     public void testHttpPostsHTTP10() throws Exception {
249         this.server.registerHandler("*", new BasicAsyncRequestHandler(new SimpleRequestHandler()));
250         final HttpHost target = start();
251 
252         this.client.setMaxPerRoute(3);
253         this.client.setMaxTotal(3);
254 
255         final String pattern = RndTestPatternGenerator.generateText();
256         final int count = RndTestPatternGenerator.generateCount(1000);
257 
258         final String expectedPattern = createExpectedString(pattern, count);
259 
260         final Queue<Future<HttpResponse>> queue = new ConcurrentLinkedQueue<Future<HttpResponse>>();
261         for (int i = 0; i < 30; i++) {
262             final BasicHttpEntityEnclosingRequest request = new BasicHttpEntityEnclosingRequest(
263                     "POST", createRequestUri(pattern, count), HttpVersion.HTTP_1_0);
264             final NStringEntity entity = new NStringEntity(expectedPattern, ContentType.DEFAULT_TEXT);
265             request.setEntity(entity);
266             final Future<HttpResponse> future = this.client.execute(target, request);
267             queue.add(future);
268         }
269 
270         while (!queue.isEmpty()) {
271             final Future<HttpResponse> future = queue.remove();
272             final HttpResponse response = future.get();
273             Assert.assertNotNull(response);
274             Assert.assertEquals(expectedPattern, EntityUtils.toString(response.getEntity()));
275         }
276     }
277 
278     @Test
279     public void testHttpPostsNoEntity() throws Exception {
280         this.server.registerHandler("*", new BasicAsyncRequestHandler(new SimpleRequestHandler()));
281         final HttpHost target = start();
282 
283         this.client.setMaxPerRoute(3);
284         this.client.setMaxTotal(3);
285 
286         final String pattern = RndTestPatternGenerator.generateText();
287         final int count = RndTestPatternGenerator.generateCount(1000);
288 
289         final Queue<Future<HttpResponse>> queue = new ConcurrentLinkedQueue<Future<HttpResponse>>();
290         for (int i = 0; i < 30; i++) {
291             final BasicHttpEntityEnclosingRequest request = new BasicHttpEntityEnclosingRequest(
292                     "POST", createRequestUri(pattern, count));
293             request.setEntity(null);
294             final Future<HttpResponse> future = this.client.execute(target, request);
295             queue.add(future);
296         }
297 
298         while (!queue.isEmpty()) {
299             final Future<HttpResponse> future = queue.remove();
300             final HttpResponse response = future.get();
301             Assert.assertNotNull(response);
302             Assert.assertEquals(HttpStatus.SC_OK, response.getStatusLine().getStatusCode());
303         }
304     }
305 
306     @Test
307     public void testHttpPostNoContentLength() throws Exception {
308         this.server.registerHandler("*", new BasicAsyncRequestHandler(new SimpleRequestHandler()));
309 
310         this.client.setHttpProcessor(new ImmutableHttpProcessor(
311                 new RequestTargetHost(),
312                 new RequestConnControl(),
313                 new RequestUserAgent(),
314                 new RequestExpectContinue(true)));
315 
316         final HttpHost target = start();
317 
318         this.client.setMaxPerRoute(3);
319         this.client.setMaxTotal(3);
320 
321         final String pattern = RndTestPatternGenerator.generateText();
322         final int count = RndTestPatternGenerator.generateCount(1000);
323 
324         final BasicHttpEntityEnclosingRequest request = new BasicHttpEntityEnclosingRequest(
325                 "POST", createRequestUri(pattern, count));
326         request.setEntity(null);
327 
328         final Future<HttpResponse> future = this.client.execute(target, request);
329 
330         final HttpResponse response = future.get();
331         Assert.assertNotNull(response);
332         Assert.assertEquals(HttpStatus.SC_OK, response.getStatusLine().getStatusCode());
333     }
334 
335     @Test
336     public void testHttpPostIdentity() throws Exception {
337         this.server.registerHandler("*", new BasicAsyncRequestHandler(new SimpleRequestHandler()));
338 
339         this.client.setHttpProcessor(new ImmutableHttpProcessor(
340                 new HttpRequestInterceptor() {
341 
342                     @Override
343                     public void process(
344                             final HttpRequest request,
345                             final HttpContext context) throws HttpException, IOException {
346                         request.addHeader(HTTP.TRANSFER_ENCODING, "identity");
347                     }
348 
349                 },
350                 new RequestTargetHost(),
351                 new RequestConnControl(),
352                 new RequestUserAgent(),
353                 new RequestExpectContinue(true)));
354 
355         final HttpHost target = start();
356 
357         this.client.setMaxPerRoute(3);
358         this.client.setMaxTotal(3);
359 
360         final String pattern = RndTestPatternGenerator.generateText();
361         final int count = RndTestPatternGenerator.generateCount(1000);
362 
363         final BasicHttpEntityEnclosingRequest request = new BasicHttpEntityEnclosingRequest(
364                 "POST", createRequestUri(pattern, count));
365         request.setEntity(null);
366 
367         final Future<HttpResponse> future = this.client.execute(target, request);
368 
369         final HttpResponse response = future.get();
370         Assert.assertNotNull(response);
371         Assert.assertEquals(HttpStatus.SC_BAD_REQUEST, response.getStatusLine().getStatusCode());
372     }
373 
374     @Test
375     public void testHttpPostsWithExpectContinue() throws Exception {
376         this.server.registerHandler("*", new BasicAsyncRequestHandler(new SimpleRequestHandler()));
377         final HttpHost target = start();
378 
379         this.client.setMaxPerRoute(3);
380         this.client.setMaxTotal(3);
381 
382         final String pattern = RndTestPatternGenerator.generateText();
383         final int count = RndTestPatternGenerator.generateCount(1000);
384 
385         final String expectedPattern = createExpectedString(pattern, count);
386 
387         final Queue<Future<HttpResponse>> queue = new ConcurrentLinkedQueue<Future<HttpResponse>>();
388         for (int i = 0; i < 30; i++) {
389             final BasicHttpEntityEnclosingRequest request = new BasicHttpEntityEnclosingRequest(
390                     "POST", createRequestUri(pattern, count));
391             final NStringEntity entity = new NStringEntity(expectedPattern, ContentType.DEFAULT_TEXT);
392             request.setEntity(entity);
393 
394             final HttpContext context = new BasicHttpContext();
395             final Future<HttpResponse> future = this.client.execute(target, request, context);
396             queue.add(future);
397         }
398 
399         while (!queue.isEmpty()) {
400             final Future<HttpResponse> future = queue.remove();
401             final HttpResponse response = future.get();
402             Assert.assertNotNull(response);
403             Assert.assertEquals(expectedPattern, EntityUtils.toString(response.getEntity()));
404         }
405     }
406 
407     @Test
408     public void testHttpPostsWithExpectationVerification() throws Exception {
409         this.server.registerHandler("*", new BasicAsyncRequestHandler(new SimpleRequestHandler()));
410         this.server.setExpectationVerifier(new HttpAsyncExpectationVerifier() {
411 
412             @Override
413             public void verify(
414                     final HttpAsyncExchange httpexchange,
415                     final HttpContext context) throws HttpException {
416                 final HttpRequest request = httpexchange.getRequest();
417                 ProtocolVersion ver = request.getRequestLine().getProtocolVersion();
418                 final String s = request.getRequestLine().getUri();
419                 if (!s.equals("AAAAAx10")) {
420                     if (!ver.lessEquals(HttpVersion.HTTP_1_1)) {
421                         ver = HttpVersion.HTTP_1_1;
422                     }
423                     final BasicHttpResponse response = new BasicHttpResponse(ver,
424                             HttpStatus.SC_EXPECTATION_FAILED, "Expectation failed");
425                     response.setEntity(new NStringEntity("Expectation failed", ContentType.TEXT_PLAIN));
426                     httpexchange.submitResponse(new BasicAsyncResponseProducer(response));
427                 } else {
428                     httpexchange.submitResponse();
429                 }
430             }
431 
432         });
433 
434         final HttpHost target = start();
435 
436         final BasicHttpEntityEnclosingRequest request1 = new BasicHttpEntityEnclosingRequest(
437                 "POST", createRequestUri("AAAAA", 10));
438         request1.setEntity(new NStringEntity(createExpectedString("AAAAA", 10)));
439         final BasicHttpEntityEnclosingRequest request2 = new BasicHttpEntityEnclosingRequest(
440                 "POST", createRequestUri("AAAAA", 10));
441         request2.setEntity(new NStringEntity(createExpectedString("AAAAA", 10)));
442         final BasicHttpEntityEnclosingRequest request3 = new BasicHttpEntityEnclosingRequest(
443                 "POST", createRequestUri("BBBBB", 10));
444         request3.setEntity(new NStringEntity(createExpectedString("BBBBB", 10)));
445 
446         final HttpRequest[] requests = new HttpRequest[] { request1, request2, request3 };
447 
448         final Queue<Future<HttpResponse>> queue = new ConcurrentLinkedQueue<Future<HttpResponse>>();
449         for (final HttpRequest request : requests) {
450             final HttpContext context = new BasicHttpContext();
451             final Future<HttpResponse> future = this.client.execute(target, request, context);
452             queue.add(future);
453         }
454 
455         final Future<HttpResponse> future1 = queue.remove();
456         final HttpResponse response1 = future1.get();
457         Assert.assertEquals(HttpStatus.SC_OK, response1.getStatusLine().getStatusCode());
458 
459         final Future<HttpResponse> future2 = queue.remove();
460         final HttpResponse response2 = future2.get();
461         Assert.assertEquals(HttpStatus.SC_OK, response2.getStatusLine().getStatusCode());
462 
463         final Future<HttpResponse> future3 = queue.remove();
464         final HttpResponse response3 = future3.get();
465         Assert.assertEquals(HttpStatus.SC_EXPECTATION_FAILED, response3.getStatusLine().getStatusCode());
466     }
467 
468     @Test
469     public void testHttpHeadsDelayedResponse() throws Exception {
470 
471         class DelayedRequestHandler implements HttpAsyncRequestHandler<HttpRequest> {
472 
473             private final SimpleRequestHandler requestHandler;
474 
475             public DelayedRequestHandler() {
476                 super();
477                 this.requestHandler = new SimpleRequestHandler();
478             }
479 
480             @Override
481             public HttpAsyncRequestConsumer<HttpRequest> processRequest(
482                     final HttpRequest request,
483                     final HttpContext context) {
484                 return new BasicAsyncRequestConsumer();
485             }
486 
487             @Override
488             public void handle(
489                     final HttpRequest request,
490                     final HttpAsyncExchange httpexchange,
491                     final HttpContext context) throws HttpException, IOException {
492                 ProtocolVersion ver = request.getRequestLine().getProtocolVersion();
493                 if (!ver.lessEquals(HttpVersion.HTTP_1_1)) {
494                     ver = HttpVersion.HTTP_1_1;
495                 }
496                 final BasicHttpResponse response = new BasicHttpResponse(ver, HttpStatus.SC_OK, "OK");
497                 new Thread() {
498                     @Override
499                     public void run() {
500                         // Wait a bit, to make sure this is delayed.
501                         try { Thread.sleep(100); } catch(final InterruptedException ie) {}
502                         // Set the entity after delaying...
503                         try {
504                             requestHandler.handle(request, response, context);
505                         } catch (final Exception ex) {
506                             response.setStatusCode(HttpStatus.SC_INTERNAL_SERVER_ERROR);
507                         }
508                         httpexchange.submitResponse(new BasicAsyncResponseProducer(response));
509                     }
510                 }.start();
511             }
512 
513         }
514 
515         this.server.registerHandler("*", new DelayedRequestHandler());
516         final HttpHost target = start();
517 
518         this.client.setMaxPerRoute(3);
519         this.client.setMaxTotal(3);
520 
521         final String pattern = RndTestPatternGenerator.generateText();
522         final int count = RndTestPatternGenerator.generateCount(1000);
523 
524         final Queue<Future<HttpResponse>> queue = new ConcurrentLinkedQueue<Future<HttpResponse>>();
525         for (int i = 0; i < 30; i++) {
526             final BasicHttpRequest request = new BasicHttpRequest("HEAD", createRequestUri(pattern, count));
527             final Future<HttpResponse> future = this.client.execute(target, request);
528             queue.add(future);
529         }
530 
531         while (!queue.isEmpty()) {
532             final Future<HttpResponse> future = queue.remove();
533             final HttpResponse response = future.get();
534             Assert.assertNotNull(response);
535             Assert.assertEquals(HttpStatus.SC_OK, response.getStatusLine().getStatusCode());
536         }
537     }
538 
539     @Test
540     public void testHttpPostsWithExpectationVerificationDelayedResponse() throws Exception {
541         this.server.registerHandler("*", new BasicAsyncRequestHandler(new SimpleRequestHandler()));
542         this.server.setExpectationVerifier(new HttpAsyncExpectationVerifier() {
543 
544             @Override
545             public void verify(
546                     final HttpAsyncExchange httpexchange,
547                     final HttpContext context) throws HttpException {
548                 new Thread() {
549                     @Override
550                     public void run() {
551                         // Wait a bit, to make sure this is delayed.
552                         try {
553                             Thread.sleep(100);
554                         } catch (final InterruptedException ie) {
555                         }
556                         // Set the entity after delaying...
557                         final HttpRequest request = httpexchange.getRequest();
558                         ProtocolVersion ver = request.getRequestLine().getProtocolVersion();
559                         final String s = request.getRequestLine().getUri();
560                         if (!s.equals("AAAAAx10")) {
561                             if (!ver.lessEquals(HttpVersion.HTTP_1_1)) {
562                                 ver = HttpVersion.HTTP_1_1;
563                             }
564                             final BasicHttpResponse response = new BasicHttpResponse(ver,
565                                     HttpStatus.SC_EXPECTATION_FAILED, "Expectation failed");
566                             response.setEntity(new NStringEntity("Expectation failed", ContentType.TEXT_PLAIN));
567                             httpexchange.submitResponse(new BasicAsyncResponseProducer(response));
568                         } else {
569                             httpexchange.submitResponse();
570                         }
571                     }
572                 }.start();
573             }
574 
575         });
576         final HttpHost target = start();
577 
578         final BasicHttpEntityEnclosingRequest request1 = new BasicHttpEntityEnclosingRequest(
579                 "POST", createRequestUri("AAAAA", 10));
580         request1.setEntity(new NStringEntity(createExpectedString("AAAAA", 10)));
581         final BasicHttpEntityEnclosingRequest request2 = new BasicHttpEntityEnclosingRequest(
582                 "POST", createRequestUri("AAAAA", 10));
583         request2.setEntity(new NStringEntity(createExpectedString("AAAAA", 10)));
584         final BasicHttpEntityEnclosingRequest request3 = new BasicHttpEntityEnclosingRequest(
585                 "POST", createRequestUri("BBBBB", 10));
586         request3.setEntity(new NStringEntity(createExpectedString("BBBBB", 10)));
587 
588         final HttpRequest[] requests = new HttpRequest[] { request1, request2, request3 };
589 
590         final Queue<Future<HttpResponse>> queue = new ConcurrentLinkedQueue<Future<HttpResponse>>();
591         for (final HttpRequest request : requests) {
592             final HttpContext context = new BasicHttpContext();
593             final Future<HttpResponse> future = this.client.execute(target, request, context);
594             queue.add(future);
595         }
596 
597         final Future<HttpResponse> future1 = queue.remove();
598         final HttpResponse response1 = future1.get();
599         Assert.assertEquals(HttpStatus.SC_OK, response1.getStatusLine().getStatusCode());
600 
601         final Future<HttpResponse> future2 = queue.remove();
602         final HttpResponse response2 = future2.get();
603         Assert.assertEquals(HttpStatus.SC_OK, response2.getStatusLine().getStatusCode());
604 
605         final Future<HttpResponse> future3 = queue.remove();
606         final HttpResponse response3 = future3.get();
607         Assert.assertEquals(HttpStatus.SC_EXPECTATION_FAILED, response3.getStatusLine().getStatusCode());
608     }
609 
610     @Test
611     public void testHttpExceptionInHandler() throws Exception {
612 
613         class FailingRequestHandler implements HttpAsyncRequestHandler<HttpRequest> {
614 
615             public FailingRequestHandler() {
616                 super();
617             }
618 
619             @Override
620             public HttpAsyncRequestConsumer<HttpRequest> processRequest(
621                     final HttpRequest request,
622                     final HttpContext context) {
623                 return new BasicAsyncRequestConsumer();
624             }
625 
626             @Override
627             public void handle(
628                     final HttpRequest request,
629                     final HttpAsyncExchange httpexchange,
630                     final HttpContext context) throws HttpException, IOException {
631                 throw new HttpException("Boom");
632             }
633 
634         }
635 
636         this.server.registerHandler("*", new FailingRequestHandler());
637         final HttpHost target = start();
638 
639         this.client.setMaxPerRoute(3);
640         this.client.setMaxTotal(3);
641 
642         final String pattern = RndTestPatternGenerator.generateText();
643         final int count = RndTestPatternGenerator.generateCount(1000);
644 
645         final Queue<Future<HttpResponse>> queue = new ConcurrentLinkedQueue<Future<HttpResponse>>();
646         for (int i = 0; i < 1; i++) {
647             final BasicHttpRequest request = new BasicHttpRequest("GET", createRequestUri(pattern, count));
648             final Future<HttpResponse> future = this.client.execute(target, request);
649             queue.add(future);
650         }
651 
652         while (!queue.isEmpty()) {
653             final Future<HttpResponse> future = queue.remove();
654             final HttpResponse response = future.get();
655             Assert.assertNotNull(response);
656             Assert.assertEquals(HttpStatus.SC_INTERNAL_SERVER_ERROR, response.getStatusLine().getStatusCode());
657         }
658     }
659 
660     @Test
661     public void testNoServiceHandler() throws Exception {
662         final HttpHost target = start();
663 
664         this.client.setMaxPerRoute(3);
665         this.client.setMaxTotal(3);
666 
667         final String pattern = RndTestPatternGenerator.generateText();
668         final int count = RndTestPatternGenerator.generateCount(1000);
669 
670         final Queue<Future<HttpResponse>> queue = new ConcurrentLinkedQueue<Future<HttpResponse>>();
671         for (int i = 0; i < 30; i++) {
672             final BasicHttpRequest request = new BasicHttpRequest("GET", createRequestUri(pattern, count));
673             final Future<HttpResponse> future = this.client.execute(target, request);
674             queue.add(future);
675         }
676 
677         while (!queue.isEmpty()) {
678             final Future<HttpResponse> future = queue.remove();
679             final HttpResponse response = future.get();
680             Assert.assertNotNull(response);
681             Assert.assertEquals(HttpStatus.SC_NOT_IMPLEMENTED, response.getStatusLine().getStatusCode());
682         }
683     }
684 
685     @Test
686     public void testResponseNoContent() throws Exception {
687         this.server.registerHandler("*", new BasicAsyncRequestHandler(new HttpRequestHandler() {
688 
689             @Override
690             public void handle(
691                     final HttpRequest request,
692                     final HttpResponse response,
693                     final HttpContext context) throws HttpException, IOException {
694                 response.setStatusCode(HttpStatus.SC_NO_CONTENT);
695             }
696 
697         }));
698         final HttpHost target = start();
699 
700         this.client.setMaxPerRoute(3);
701         this.client.setMaxTotal(3);
702 
703         final Queue<Future<HttpResponse>> queue = new ConcurrentLinkedQueue<Future<HttpResponse>>();
704         for (int i = 0; i < 30; i++) {
705             final BasicHttpRequest request = new BasicHttpRequest("GET", "/");
706             final Future<HttpResponse> future = this.client.execute(target, request);
707             queue.add(future);
708         }
709 
710         while (!queue.isEmpty()) {
711             final Future<HttpResponse> future = queue.remove();
712             final HttpResponse response = future.get();
713             Assert.assertNotNull(response);
714             Assert.assertNull(response.getEntity());
715         }
716     }
717 
718 }