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.protocol;
29  
30  import java.io.IOException;
31  import java.net.SocketTimeoutException;
32  
33  import org.apache.http.ConnectionClosedException;
34  import org.apache.http.HttpException;
35  import org.apache.http.HttpRequest;
36  import org.apache.http.HttpStatus;
37  import org.apache.http.HttpVersion;
38  import org.apache.http.entity.BasicHttpEntity;
39  import org.apache.http.message.BasicHttpEntityEnclosingRequest;
40  import org.apache.http.message.BasicHttpRequest;
41  import org.apache.http.message.BasicHttpResponse;
42  import org.apache.http.nio.ContentDecoder;
43  import org.apache.http.nio.ContentEncoder;
44  import org.apache.http.nio.NHttpClientConnection;
45  import org.apache.http.nio.NHttpConnection;
46  import org.apache.http.nio.entity.NStringEntity;
47  import org.apache.http.nio.protocol.HttpAsyncRequestExecutor.State;
48  import org.apache.http.protocol.BasicHttpContext;
49  import org.apache.http.protocol.HTTP;
50  import org.apache.http.protocol.HttpContext;
51  import org.junit.After;
52  import org.junit.Assert;
53  import org.junit.Before;
54  import org.junit.Test;
55  import org.mockito.Matchers;
56  import org.mockito.Mockito;
57  
58  public class TestHttpAsyncRequestExecutor {
59  
60      private HttpAsyncRequestExecutor protocolHandler;
61      private HttpContext connContext;
62      private NHttpClientConnection conn;
63      private HttpAsyncClientExchangeHandler exchangeHandler;
64      private ContentEncoder encoder;
65      private ContentDecoder decoder;
66  
67      @Before
68      public void setUp() throws Exception {
69          this.protocolHandler = new HttpAsyncRequestExecutor();
70          this.connContext = new BasicHttpContext();
71          this.conn = Mockito.mock(NHttpClientConnection.class);
72          this.exchangeHandler = Mockito.mock(HttpAsyncClientExchangeHandler.class);
73          this.encoder = Mockito.mock(ContentEncoder.class);
74          this.decoder = Mockito.mock(ContentDecoder.class);
75          Mockito.when(this.conn.getContext()).thenReturn(this.connContext);
76      }
77  
78      @After
79      public void tearDown() throws Exception {
80      }
81  
82      @Test
83      public void testConnected() throws Exception {
84          final HttpRequest request = new BasicHttpRequest("GET", "/");
85          Mockito.when(this.exchangeHandler.generateRequest()).thenReturn(request);
86          this.connContext.setAttribute(HttpAsyncRequestExecutor.HTTP_HANDLER, this.exchangeHandler);
87  
88          this.protocolHandler.connected(this.conn, null);
89  
90          final State state = (State) this.connContext.getAttribute(
91                  HttpAsyncRequestExecutor.HTTP_EXCHANGE_STATE);
92          Assert.assertNotNull(state);
93          Mockito.verify(this.exchangeHandler).generateRequest();
94          Assert.assertSame(request, state.getRequest());
95          Mockito.verify(this.conn).submitRequest(request);
96          Mockito.verify(this.exchangeHandler).requestCompleted();
97          Assert.assertEquals(MessageState.COMPLETED, state.getRequestState());
98          Assert.assertEquals("request state: COMPLETED; request: GET / HTTP/1.1; " +
99                  "response state: READY; response: ; valid: true;", state.toString());
100     }
101 
102     @Test
103     public void testClosed() throws Exception {
104         final State state = new HttpAsyncRequestExecutor.State();
105         state.setRequestState(MessageState.READY);
106         state.setResponseState(MessageState.READY);
107         this.connContext.setAttribute(HttpAsyncRequestExecutor.HTTP_EXCHANGE_STATE, state);
108         this.connContext.setAttribute(HttpAsyncRequestExecutor.HTTP_HANDLER, this.exchangeHandler);
109 
110         this.protocolHandler.closed(this.conn);
111 
112         Mockito.verify(this.exchangeHandler, Mockito.never()).close();
113     }
114 
115     @Test
116     public void testClosedNullState() throws Exception {
117         this.connContext.setAttribute(HttpAsyncRequestExecutor.HTTP_HANDLER, this.exchangeHandler);
118 
119         this.protocolHandler.closed(this.conn);
120 
121         Mockito.verify(this.exchangeHandler).close();
122     }
123 
124     @Test
125     public void testClosedInconsistentState() throws Exception {
126         final State state = new HttpAsyncRequestExecutor.State();
127         state.setRequestState(MessageState.COMPLETED);
128         state.setResponseState(MessageState.INIT);
129         this.connContext.setAttribute(HttpAsyncRequestExecutor.HTTP_EXCHANGE_STATE, state);
130         this.connContext.setAttribute(HttpAsyncRequestExecutor.HTTP_HANDLER, this.exchangeHandler);
131 
132         this.protocolHandler.closed(this.conn);
133 
134         Mockito.verify(this.exchangeHandler).failed(Matchers.any(ConnectionClosedException.class));
135     }
136 
137     @Test
138     public void testHttpExceptionHandling() throws Exception {
139         final State state = new HttpAsyncRequestExecutor.State();
140         state.setRequestState(MessageState.COMPLETED);
141         state.setResponseState(MessageState.COMPLETED);
142         this.connContext.setAttribute(HttpAsyncRequestExecutor.HTTP_EXCHANGE_STATE, state);
143         this.connContext.setAttribute(HttpAsyncRequestExecutor.HTTP_HANDLER, this.exchangeHandler);
144 
145         final HttpException httpex = new HttpException();
146         this.protocolHandler.exception(this.conn, httpex);
147 
148         Mockito.verify(this.exchangeHandler).failed(httpex);
149         Mockito.verify(this.conn).shutdown();
150     }
151 
152     @Test
153     public void testIOExceptionHandling() throws Exception {
154         final State state = new HttpAsyncRequestExecutor.State();
155         state.setRequestState(MessageState.COMPLETED);
156         state.setResponseState(MessageState.COMPLETED);
157         this.connContext.setAttribute(HttpAsyncRequestExecutor.HTTP_EXCHANGE_STATE, state);
158         this.connContext.setAttribute(HttpAsyncRequestExecutor.HTTP_HANDLER, this.exchangeHandler);
159 
160         final IOException ioex = new IOException();
161         this.protocolHandler.exception(this.conn, ioex);
162 
163         Mockito.verify(this.exchangeHandler).failed(ioex);
164         Mockito.verify(this.conn).shutdown();
165     }
166 
167     @Test
168     public void testBasicRequest() throws Exception {
169         final State state = new HttpAsyncRequestExecutor.State();
170         this.connContext.setAttribute(HttpAsyncRequestExecutor.HTTP_EXCHANGE_STATE, state);
171         this.connContext.setAttribute(HttpAsyncRequestExecutor.HTTP_HANDLER, this.exchangeHandler);
172         final HttpRequest request = new BasicHttpRequest("GET", "/");
173         Mockito.when(this.exchangeHandler.generateRequest()).thenReturn(request);
174 
175         this.protocolHandler.requestReady(this.conn);
176 
177         Mockito.verify(this.exchangeHandler).generateRequest();
178         Assert.assertSame(request, state.getRequest());
179 
180         Mockito.verify(this.conn).submitRequest(request);
181         Mockito.verify(this.exchangeHandler).requestCompleted();
182         Assert.assertEquals(MessageState.COMPLETED, state.getRequestState());
183     }
184 
185     @Test
186     public void testNullRequest() throws Exception {
187         final State state = new HttpAsyncRequestExecutor.State();
188         this.connContext.setAttribute(HttpAsyncRequestExecutor.HTTP_EXCHANGE_STATE, state);
189         this.connContext.setAttribute(HttpAsyncRequestExecutor.HTTP_HANDLER, this.exchangeHandler);
190         Mockito.when(this.exchangeHandler.generateRequest()).thenReturn(null);
191 
192         this.protocolHandler.requestReady(this.conn);
193 
194         Mockito.verify(this.exchangeHandler).generateRequest();
195         Assert.assertNull(state.getRequest());
196 
197         Mockito.verify(this.conn, Mockito.times(1)).suspendOutput();
198         Mockito.verify(this.conn, Mockito.never()).submitRequest(Matchers.<HttpRequest>any());
199     }
200 
201     @Test
202     public void testEntityEnclosingRequestWithoutExpectContinue() throws Exception {
203         final State state = new HttpAsyncRequestExecutor.State();
204         this.connContext.setAttribute(HttpAsyncRequestExecutor.HTTP_EXCHANGE_STATE, state);
205         this.connContext.setAttribute(HttpAsyncRequestExecutor.HTTP_HANDLER, this.exchangeHandler);
206         final BasicHttpEntityEnclosingRequest request = new BasicHttpEntityEnclosingRequest("POST", "/");
207         request.setEntity(new NStringEntity("stuff"));
208         Mockito.when(this.exchangeHandler.generateRequest()).thenReturn(request);
209 
210         this.protocolHandler.requestReady(this.conn);
211 
212         Mockito.verify(this.exchangeHandler).generateRequest();
213         Assert.assertSame(request, state.getRequest());
214         Mockito.verify(this.conn).submitRequest(request);
215         Mockito.verify(this.exchangeHandler, Mockito.never()).requestCompleted();
216         Assert.assertEquals(MessageState.BODY_STREAM, state.getRequestState());
217     }
218 
219     @Test
220     public void testEntityEnclosingRequestWithExpectContinue() throws Exception {
221         final State state = new HttpAsyncRequestExecutor.State();
222         this.connContext.setAttribute(HttpAsyncRequestExecutor.HTTP_EXCHANGE_STATE, state);
223         this.connContext.setAttribute(HttpAsyncRequestExecutor.HTTP_HANDLER, this.exchangeHandler);
224         final BasicHttpEntityEnclosingRequest request = new BasicHttpEntityEnclosingRequest("POST", "/");
225         request.setHeader(HTTP.EXPECT_DIRECTIVE, HTTP.EXPECT_CONTINUE);
226         Mockito.when(this.exchangeHandler.generateRequest()).thenReturn(request);
227         Mockito.when(this.conn.getSocketTimeout()).thenReturn(1000);
228 
229         this.protocolHandler.requestReady(this.conn);
230 
231         Mockito.verify(this.exchangeHandler).generateRequest();
232         Assert.assertSame(request, state.getRequest());
233         Mockito.verify(this.conn).submitRequest(request);
234         Mockito.verify(this.conn).setSocketTimeout(3000);
235         Assert.assertEquals(1000, state.getTimeout());
236         Mockito.verify(this.exchangeHandler, Mockito.never()).requestCompleted();
237         Assert.assertEquals(MessageState.ACK_EXPECTED, state.getRequestState());
238     }
239 
240     @Test
241     public void testRequestContentOutput() throws Exception {
242         final State state = new HttpAsyncRequestExecutor.State();
243         state.setRequestState(MessageState.BODY_STREAM);
244         this.connContext.setAttribute(HttpAsyncRequestExecutor.HTTP_EXCHANGE_STATE, state);
245         this.connContext.setAttribute(HttpAsyncRequestExecutor.HTTP_HANDLER, this.exchangeHandler);
246         Mockito.when(this.encoder.isCompleted()).thenReturn(Boolean.FALSE);
247 
248         this.protocolHandler.outputReady(this.conn, this.encoder);
249 
250         Mockito.verify(this.exchangeHandler).produceContent(this.encoder, this.conn);
251         Assert.assertEquals(MessageState.BODY_STREAM, state.getRequestState());
252     }
253 
254     @Test
255     public void testRequestContentOutputCompleted() throws Exception {
256         final State state = new HttpAsyncRequestExecutor.State();
257         state.setRequestState(MessageState.BODY_STREAM);
258         this.connContext.setAttribute(HttpAsyncRequestExecutor.HTTP_EXCHANGE_STATE, state);
259         this.connContext.setAttribute(HttpAsyncRequestExecutor.HTTP_HANDLER, this.exchangeHandler);
260         Mockito.when(this.encoder.isCompleted()).thenReturn(Boolean.TRUE);
261 
262         this.protocolHandler.outputReady(this.conn, this.encoder);
263 
264         Mockito.verify(this.exchangeHandler).produceContent(this.encoder, this.conn);
265         Mockito.verify(this.exchangeHandler).requestCompleted();
266         Assert.assertEquals(MessageState.COMPLETED, state.getRequestState());
267     }
268 
269     @Test
270     public void testRequestContentContinueExpected() throws Exception {
271         final State state = new HttpAsyncRequestExecutor.State();
272         state.setRequestState(MessageState.ACK_EXPECTED);
273         this.connContext.setAttribute(HttpAsyncRequestExecutor.HTTP_EXCHANGE_STATE, state);
274         this.connContext.setAttribute(HttpAsyncRequestExecutor.HTTP_HANDLER, this.exchangeHandler);
275 
276         this.protocolHandler.outputReady(this.conn, this.encoder);
277 
278         Mockito.verify(this.conn).suspendOutput();
279         Mockito.verify(this.exchangeHandler, Mockito.never()).produceContent(this.encoder, this.conn);
280         Assert.assertEquals(MessageState.ACK_EXPECTED, state.getRequestState());
281     }
282 
283     @Test
284     public void testBasicResponse() throws Exception {
285         final State state = new HttpAsyncRequestExecutor.State();
286         final HttpRequest request = new BasicHttpRequest("GET", "/");
287         state.setRequest(request);
288         this.connContext.setAttribute(HttpAsyncRequestExecutor.HTTP_EXCHANGE_STATE, state);
289         this.connContext.setAttribute(HttpAsyncRequestExecutor.HTTP_HANDLER, this.exchangeHandler);
290         final BasicHttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, 200, "OK");
291         Mockito.when(this.conn.getHttpResponse()).thenReturn(response);
292 
293         this.protocolHandler.responseReceived(this.conn);
294 
295         Assert.assertSame(response, state.getResponse());
296         Assert.assertEquals(MessageState.BODY_STREAM, state.getResponseState());
297     }
298 
299     @Test
300     public void testResponseContinue() throws Exception {
301         final State state = new HttpAsyncRequestExecutor.State();
302         state.setRequestState(MessageState.ACK_EXPECTED);
303         state.setTimeout(1000);
304         final BasicHttpEntityEnclosingRequest request = new BasicHttpEntityEnclosingRequest("POST", "/");
305         request.setEntity(new NStringEntity("stuff"));
306         state.setRequest(request);
307         this.connContext.setAttribute(HttpAsyncRequestExecutor.HTTP_EXCHANGE_STATE, state);
308         this.connContext.setAttribute(HttpAsyncRequestExecutor.HTTP_HANDLER, this.exchangeHandler);
309         final BasicHttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, 100, "Continue");
310         Mockito.when(this.conn.getHttpResponse()).thenReturn(response);
311 
312         this.protocolHandler.responseReceived(this.conn);
313 
314         Assert.assertNull(state.getResponse());
315         Assert.assertEquals(MessageState.BODY_STREAM, state.getRequestState());
316         Assert.assertEquals(MessageState.READY, state.getResponseState());
317         Mockito.verify(this.conn).setSocketTimeout(1000);
318         Mockito.verify(this.conn).requestOutput();
319     }
320 
321     @Test
322     public void testResponseContinueOutOfSequence() throws Exception {
323         final State state = new HttpAsyncRequestExecutor.State();
324         state.setRequestState(MessageState.COMPLETED);
325         final BasicHttpEntityEnclosingRequest request = new BasicHttpEntityEnclosingRequest("POST", "/");
326         request.setEntity(new NStringEntity("stuff"));
327         state.setRequest(request);
328         this.connContext.setAttribute(HttpAsyncRequestExecutor.HTTP_EXCHANGE_STATE, state);
329         this.connContext.setAttribute(HttpAsyncRequestExecutor.HTTP_HANDLER, this.exchangeHandler);
330         final BasicHttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, 100, "Continue");
331         Mockito.when(this.conn.getHttpResponse()).thenReturn(response);
332 
333         this.protocolHandler.responseReceived(this.conn);
334 
335         Assert.assertNull(state.getResponse());
336         Assert.assertEquals(MessageState.COMPLETED, state.getRequestState());
337         Mockito.verify(this.conn, Mockito.never()).requestOutput();
338     }
339 
340     @Test(expected=HttpException.class)
341     public void testResponseUnsupported1xx() throws Exception {
342         final State state = new HttpAsyncRequestExecutor.State();
343         state.setRequestState(MessageState.ACK_EXPECTED);
344         state.setTimeout(1000);
345         final BasicHttpEntityEnclosingRequest request = new BasicHttpEntityEnclosingRequest("POST", "/");
346         request.setEntity(new NStringEntity("stuff"));
347         state.setRequest(request);
348         this.connContext.setAttribute(HttpAsyncRequestExecutor.HTTP_EXCHANGE_STATE, state);
349         this.connContext.setAttribute(HttpAsyncRequestExecutor.HTTP_HANDLER, this.exchangeHandler);
350         final BasicHttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, 111, "WTF?");
351         Mockito.when(this.conn.getHttpResponse()).thenReturn(response);
352 
353         this.protocolHandler.responseReceived(this.conn);
354     }
355 
356     @Test
357     public void testResponseExpectationFailed() throws Exception {
358         final State state = new HttpAsyncRequestExecutor.State();
359         state.setRequestState(MessageState.ACK_EXPECTED);
360         state.setTimeout(1000);
361         final BasicHttpEntityEnclosingRequest request = new BasicHttpEntityEnclosingRequest("POST", "/");
362         request.setEntity(new NStringEntity("stuff"));
363         state.setRequest(request);
364         this.connContext.setAttribute(HttpAsyncRequestExecutor.HTTP_EXCHANGE_STATE, state);
365         this.connContext.setAttribute(HttpAsyncRequestExecutor.HTTP_HANDLER, this.exchangeHandler);
366         final BasicHttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, 403, "Unauthorized");
367         Mockito.when(this.conn.getHttpResponse()).thenReturn(response);
368 
369         this.protocolHandler.responseReceived(this.conn);
370 
371         Assert.assertSame(response, state.getResponse());
372         Assert.assertEquals(MessageState.COMPLETED, state.getRequestState());
373         Assert.assertEquals(MessageState.BODY_STREAM, state.getResponseState());
374         Mockito.verify(this.conn).setSocketTimeout(1000);
375         Mockito.verify(this.conn).resetOutput();
376     }
377 
378     @Test
379     public void testEarlyResponse() throws Exception {
380         final State state = new HttpAsyncRequestExecutor.State();
381         state.setRequestState(MessageState.BODY_STREAM);
382         state.setTimeout(1000);
383         final BasicHttpEntityEnclosingRequest request = new BasicHttpEntityEnclosingRequest("POST", "/");
384         request.setEntity(new NStringEntity("stuff"));
385         state.setRequest(request);
386         this.connContext.setAttribute(HttpAsyncRequestExecutor.HTTP_EXCHANGE_STATE, state);
387         this.connContext.setAttribute(HttpAsyncRequestExecutor.HTTP_HANDLER, this.exchangeHandler);
388         final BasicHttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, 403, "Unauthorized");
389         Mockito.when(this.conn.getHttpResponse()).thenReturn(response);
390 
391         this.protocolHandler.responseReceived(this.conn);
392 
393         Assert.assertSame(response, state.getResponse());
394         Assert.assertEquals(MessageState.COMPLETED, state.getRequestState());
395         Assert.assertEquals(MessageState.BODY_STREAM, state.getResponseState());
396         Mockito.verify(this.conn).suspendOutput();
397         Mockito.verify(this.conn).resetOutput();
398         Assert.assertFalse(state.isValid());
399     }
400 
401     @Test
402     public void testEarlyNonErrorResponse() throws Exception {
403         final State state = new HttpAsyncRequestExecutor.State();
404         state.setRequestState(MessageState.BODY_STREAM);
405         state.setTimeout(1000);
406         final BasicHttpEntityEnclosingRequest request = new BasicHttpEntityEnclosingRequest("POST", "/");
407         request.setEntity(new NStringEntity("stuff"));
408         state.setRequest(request);
409         this.connContext.setAttribute(HttpAsyncRequestExecutor.HTTP_EXCHANGE_STATE, state);
410         this.connContext.setAttribute(HttpAsyncRequestExecutor.HTTP_HANDLER, this.exchangeHandler);
411         final BasicHttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, 200, "OK");
412         Mockito.when(this.conn.getHttpResponse()).thenReturn(response);
413 
414         this.protocolHandler.responseReceived(this.conn);
415 
416         Assert.assertSame(response, state.getResponse());
417         Assert.assertEquals(MessageState.BODY_STREAM, state.getRequestState());
418         Assert.assertEquals(MessageState.BODY_STREAM, state.getResponseState());
419         Mockito.verify(this.conn, Mockito.never()).suspendOutput();
420         Mockito.verify(this.conn, Mockito.never()).resetOutput();
421         Assert.assertTrue(state.isValid());
422     }
423 
424     @Test
425     public void testResponseToHead() throws Exception {
426         final State state = new HttpAsyncRequestExecutor.State();
427         final HttpRequest request = new BasicHttpRequest("HEAD", "/");
428         state.setRequest(request);
429         this.connContext.setAttribute(HttpAsyncRequestExecutor.HTTP_EXCHANGE_STATE, state);
430         this.connContext.setAttribute(HttpAsyncRequestExecutor.HTTP_HANDLER, this.exchangeHandler);
431         final BasicHttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, 200, "OK");
432         Mockito.when(this.conn.getHttpResponse()).thenReturn(response);
433 
434         this.protocolHandler.responseReceived(this.conn);
435 
436         Assert.assertEquals(MessageState.READY, state.getResponseState());
437         Assert.assertEquals(MessageState.READY, state.getRequestState());
438         Assert.assertNull(state.getRequest());
439         Assert.assertNull(state.getResponse());
440         Mockito.verify(this.exchangeHandler).responseReceived(response);
441         Mockito.verify(this.conn).resetInput();
442         Mockito.verify(this.conn, Mockito.never()).close();
443     }
444 
445     @Test
446     public void testResponseToConnect() throws Exception {
447         final State state = new HttpAsyncRequestExecutor.State();
448         final HttpRequest request = new BasicHttpRequest("Connect", "/");
449         state.setRequest(request);
450         this.connContext.setAttribute(HttpAsyncRequestExecutor.HTTP_EXCHANGE_STATE, state);
451         this.connContext.setAttribute(HttpAsyncRequestExecutor.HTTP_HANDLER, this.exchangeHandler);
452         final BasicHttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, 200, "OK");
453         Mockito.when(this.conn.getHttpResponse()).thenReturn(response);
454 
455         this.protocolHandler.responseReceived(this.conn);
456 
457         Assert.assertEquals(MessageState.READY, state.getResponseState());
458         Assert.assertEquals(MessageState.READY, state.getRequestState());
459         Assert.assertNull(state.getRequest());
460         Assert.assertNull(state.getResponse());
461         Mockito.verify(this.exchangeHandler).responseReceived(response);
462         Mockito.verify(this.conn).resetInput();
463         Mockito.verify(this.conn, Mockito.never()).close();
464     }
465 
466     @Test
467     public void testResponseNotModified() throws Exception {
468         final State state = new HttpAsyncRequestExecutor.State();
469         final HttpRequest request = new BasicHttpRequest("Connect", "/");
470         state.setRequest(request);
471         this.connContext.setAttribute(HttpAsyncRequestExecutor.HTTP_EXCHANGE_STATE, state);
472         this.connContext.setAttribute(HttpAsyncRequestExecutor.HTTP_HANDLER, this.exchangeHandler);
473         final BasicHttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1,
474                 HttpStatus.SC_NOT_MODIFIED, "Not modified");
475         response.setEntity(new BasicHttpEntity());
476         Mockito.when(this.conn.getHttpResponse()).thenReturn(response);
477 
478         this.protocolHandler.responseReceived(this.conn);
479 
480         Assert.assertEquals(MessageState.READY, state.getResponseState());
481         Assert.assertEquals(MessageState.READY, state.getRequestState());
482         Assert.assertNull(state.getRequest());
483         Assert.assertNull(state.getResponse());
484         Assert.assertNull(response.getEntity());
485         Mockito.verify(this.exchangeHandler).responseReceived(response);
486         Mockito.verify(this.conn).resetInput();
487         Mockito.verify(this.conn, Mockito.never()).close();
488     }
489 
490     @Test
491     public void testResponseContentInput() throws Exception {
492         final State state = new HttpAsyncRequestExecutor.State();
493         state.setResponseState(MessageState.BODY_STREAM);
494         this.connContext.setAttribute(HttpAsyncRequestExecutor.HTTP_EXCHANGE_STATE, state);
495         this.connContext.setAttribute(HttpAsyncRequestExecutor.HTTP_HANDLER, this.exchangeHandler);
496         Mockito.when(this.decoder.isCompleted()).thenReturn(Boolean.FALSE);
497 
498         this.protocolHandler.inputReady(this.conn, this.decoder);
499 
500         Mockito.verify(this.exchangeHandler).consumeContent(this.decoder, this.conn);
501         Assert.assertEquals(MessageState.BODY_STREAM, state.getResponseState());
502     }
503 
504     @Test
505     public void testResponseContentOutputCompleted() throws Exception {
506         final State state = new HttpAsyncRequestExecutor.State();
507         final HttpRequest request = new BasicHttpRequest("GET", "/");
508         state.setRequest(request);
509         state.setResponseState(MessageState.BODY_STREAM);
510         final BasicHttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, 200, "OK");
511         state.setResponse(response);
512         Mockito.when(this.exchangeHandler.isDone()).thenReturn(Boolean.TRUE);
513         this.connContext.setAttribute(HttpAsyncRequestExecutor.HTTP_EXCHANGE_STATE, state);
514         this.connContext.setAttribute(HttpAsyncRequestExecutor.HTTP_HANDLER, this.exchangeHandler);
515         Mockito.when(this.decoder.isCompleted()).thenReturn(Boolean.TRUE);
516 
517         this.protocolHandler.inputReady(this.conn, this.decoder);
518 
519         Assert.assertEquals(MessageState.READY, state.getRequestState());
520         Assert.assertEquals(MessageState.READY, state.getResponseState());
521         Mockito.verify(this.exchangeHandler).consumeContent(this.decoder, this.conn);
522         Mockito.verify(this.exchangeHandler).responseCompleted();
523         Mockito.verify(this.conn, Mockito.never()).close();
524     }
525 
526     @Test
527     public void testResponseContentOutputCompletedHandlerNotDone() throws Exception {
528         final State state = new HttpAsyncRequestExecutor.State();
529         state.setResponseState(MessageState.BODY_STREAM);
530         final HttpRequest request = new BasicHttpRequest("GET", "/");
531         state.setRequest(request);
532         final BasicHttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, 200, "OK");
533         state.setResponse(response);
534         Mockito.when(this.exchangeHandler.isDone()).thenReturn(Boolean.FALSE);
535         this.connContext.setAttribute(HttpAsyncRequestExecutor.HTTP_EXCHANGE_STATE, state);
536         this.connContext.setAttribute(HttpAsyncRequestExecutor.HTTP_HANDLER, this.exchangeHandler);
537         Mockito.when(this.decoder.isCompleted()).thenReturn(Boolean.TRUE);
538         Mockito.when(this.conn.isOpen()).thenReturn(Boolean.TRUE);
539 
540         this.protocolHandler.inputReady(this.conn, this.decoder);
541 
542         Assert.assertEquals(MessageState.READY, state.getRequestState());
543         Assert.assertEquals(MessageState.READY, state.getResponseState());
544         Mockito.verify(this.exchangeHandler).consumeContent(this.decoder, this.conn);
545         Mockito.verify(this.exchangeHandler).responseCompleted();
546         Mockito.verify(this.conn).requestOutput();
547     }
548 
549     @Test
550     public void testResponseContentOutputCompletedHandlerNotDoneConnClosed() throws Exception {
551         final State state = new HttpAsyncRequestExecutor.State();
552         final HttpRequest request = new BasicHttpRequest("GET", "/");
553         state.setRequest(request);
554         state.setResponseState(MessageState.BODY_STREAM);
555         final BasicHttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, 200, "OK");
556         state.setResponse(response);
557         Mockito.when(this.exchangeHandler.isDone()).thenReturn(Boolean.FALSE);
558         this.connContext.setAttribute(HttpAsyncRequestExecutor.HTTP_EXCHANGE_STATE, state);
559         this.connContext.setAttribute(HttpAsyncRequestExecutor.HTTP_HANDLER, this.exchangeHandler);
560         Mockito.when(this.decoder.isCompleted()).thenReturn(Boolean.TRUE);
561         Mockito.when(this.conn.isOpen()).thenReturn(Boolean.FALSE);
562 
563         this.protocolHandler.inputReady(this.conn, this.decoder);
564 
565         Assert.assertEquals(MessageState.READY, state.getRequestState());
566         Assert.assertEquals(MessageState.READY, state.getResponseState());
567         Mockito.verify(this.exchangeHandler).consumeContent(this.decoder, this.conn);
568         Mockito.verify(this.exchangeHandler).responseCompleted();
569         Mockito.verify(this.conn, Mockito.never()).requestOutput();
570     }
571 
572     @Test
573     public void testResponseInvalidState() throws Exception {
574         final State state = new HttpAsyncRequestExecutor.State();
575         final HttpRequest request = new BasicHttpRequest("GET", "/");
576         state.setRequest(request);
577         state.setResponseState(MessageState.BODY_STREAM);
578         final BasicHttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, 200, "OK");
579         state.setResponse(response);
580         state.invalidate();
581         this.connContext.setAttribute(HttpAsyncRequestExecutor.HTTP_EXCHANGE_STATE, state);
582         this.connContext.setAttribute(HttpAsyncRequestExecutor.HTTP_HANDLER, this.exchangeHandler);
583         Mockito.when(this.decoder.isCompleted()).thenReturn(Boolean.TRUE);
584 
585         this.protocolHandler.inputReady(this.conn, this.decoder);
586 
587         Assert.assertEquals(MessageState.READY, state.getRequestState());
588         Assert.assertEquals(MessageState.READY, state.getResponseState());
589         Mockito.verify(this.exchangeHandler).consumeContent(this.decoder, this.conn);
590         Mockito.verify(this.conn).close();
591     }
592 
593     @Test
594     public void testEndOfInput() throws Exception {
595         final State state = new HttpAsyncRequestExecutor.State();
596         this.connContext.setAttribute(HttpAsyncRequestExecutor.HTTP_EXCHANGE_STATE, state);
597 
598         this.protocolHandler.endOfInput(this.conn);
599 
600         Mockito.verify(this.conn).close();
601     }
602 
603     @Test
604     public void testPrematureEndOfInput() throws Exception {
605         final State state = new HttpAsyncRequestExecutor.State();
606         state.setRequestState(MessageState.COMPLETED);
607         this.connContext.setAttribute(HttpAsyncRequestExecutor.HTTP_EXCHANGE_STATE, state);
608         this.connContext.setAttribute(HttpAsyncRequestExecutor.HTTP_HANDLER, this.exchangeHandler);
609 
610         this.protocolHandler.endOfInput(this.conn);
611 
612         Assert.assertFalse(state.isValid());
613 
614         Mockito.verify(this.conn).close();
615         Mockito.verify(this.exchangeHandler).failed(Matchers.any(ConnectionClosedException.class));
616     }
617 
618     @Test
619     public void testPrematureEndOfInputRequestReady() throws Exception {
620         final State state = new HttpAsyncRequestExecutor.State();
621         state.setRequestState(MessageState.READY);
622         this.connContext.setAttribute(HttpAsyncRequestExecutor.HTTP_EXCHANGE_STATE, state);
623         this.connContext.setAttribute(HttpAsyncRequestExecutor.HTTP_HANDLER, this.exchangeHandler);
624 
625         this.protocolHandler.endOfInput(this.conn);
626 
627         Assert.assertTrue(state.isValid());
628 
629         Mockito.verify(this.exchangeHandler).inputTerminated();
630     }
631 
632     @Test
633     public void testTimeoutNoHandler() throws Exception {
634         final State state = new HttpAsyncRequestExecutor.State();
635         this.connContext.setAttribute(HttpAsyncRequestExecutor.HTTP_EXCHANGE_STATE, state);
636 
637         Mockito.when(this.conn.getStatus()).thenReturn(
638                 NHttpConnection.ACTIVE, NHttpConnection.CLOSING);
639 
640         this.protocolHandler.timeout(this.conn);
641 
642         Mockito.verify(this.conn).close();
643         Mockito.verify(this.conn).setSocketTimeout(250);
644     }
645 
646     @Test
647     public void testExpectContinueTimeout() throws Exception {
648         final State state = new HttpAsyncRequestExecutor.State();
649         state.setRequestState(MessageState.ACK_EXPECTED);
650         state.setTimeout(1000);
651         this.connContext.setAttribute(HttpAsyncRequestExecutor.HTTP_EXCHANGE_STATE, state);
652         this.connContext.setAttribute(HttpAsyncRequestExecutor.HTTP_HANDLER, this.exchangeHandler);
653 
654         this.protocolHandler.timeout(this.conn);
655 
656         Assert.assertEquals(MessageState.BODY_STREAM, state.getRequestState());
657         Assert.assertTrue(state.isValid());
658         Mockito.verify(this.conn).setSocketTimeout(1000);
659         Mockito.verify(this.conn).requestOutput();
660     }
661 
662     @Test
663     public void testTimeoutActiveConnection() throws Exception {
664         final State state = new HttpAsyncRequestExecutor.State();
665         state.setRequestState(MessageState.BODY_STREAM);
666         this.connContext.setAttribute(HttpAsyncRequestExecutor.HTTP_EXCHANGE_STATE, state);
667         this.connContext.setAttribute(HttpAsyncRequestExecutor.HTTP_HANDLER, this.exchangeHandler);
668         Mockito.when(this.conn.getStatus()).thenReturn(NHttpConnection.ACTIVE, NHttpConnection.CLOSED);
669 
670         this.protocolHandler.timeout(this.conn);
671 
672         Assert.assertEquals(MessageState.BODY_STREAM, state.getRequestState());
673         Assert.assertFalse(state.isValid());
674         Mockito.verify(this.exchangeHandler).failed(Matchers.any(SocketTimeoutException.class));
675         Mockito.verify(this.exchangeHandler).close();
676         Mockito.verify(this.conn).close();
677         Mockito.verify(this.conn, Mockito.never()).setSocketTimeout(Matchers.anyInt());
678     }
679 
680     @Test
681     public void testTimeoutActiveConnectionBufferedData() throws Exception {
682         final State state = new HttpAsyncRequestExecutor.State();
683         state.setRequestState(MessageState.BODY_STREAM);
684         this.connContext.setAttribute(HttpAsyncRequestExecutor.HTTP_EXCHANGE_STATE, state);
685         this.connContext.setAttribute(HttpAsyncRequestExecutor.HTTP_HANDLER, this.exchangeHandler);
686         Mockito.when(this.conn.getStatus()).thenReturn(NHttpConnection.ACTIVE, NHttpConnection.CLOSING);
687 
688         this.protocolHandler.timeout(this.conn);
689 
690         Assert.assertEquals(MessageState.BODY_STREAM, state.getRequestState());
691         Assert.assertFalse(state.isValid());
692         Mockito.verify(this.exchangeHandler).failed(Matchers.any(SocketTimeoutException.class));
693         Mockito.verify(this.exchangeHandler).close();
694         Mockito.verify(this.conn).close();
695         Mockito.verify(this.conn).setSocketTimeout(250);
696     }
697 
698     @Test
699     public void testTimeoutClosingConnection() throws Exception {
700         final State state = new HttpAsyncRequestExecutor.State();
701         state.setRequestState(MessageState.BODY_STREAM);
702         this.connContext.setAttribute(HttpAsyncRequestExecutor.HTTP_EXCHANGE_STATE, state);
703         this.connContext.setAttribute(HttpAsyncRequestExecutor.HTTP_HANDLER, this.exchangeHandler);
704         Mockito.when(this.conn.getStatus()).thenReturn(NHttpConnection.CLOSING, NHttpConnection.CLOSED);
705 
706         this.protocolHandler.timeout(this.conn);
707 
708         Assert.assertEquals(MessageState.BODY_STREAM, state.getRequestState());
709         Assert.assertFalse(state.isValid());
710         Mockito.verify(this.exchangeHandler).failed(Matchers.any(SocketTimeoutException.class));
711         Mockito.verify(this.exchangeHandler).close();
712         Mockito.verify(this.conn).shutdown();
713     }
714 
715     @Test
716     public void testExchangeDone() throws Exception {
717         final State state = new HttpAsyncRequestExecutor.State();
718         final HttpRequest request = new BasicHttpRequest("GET", "/");
719         state.setRequest(request);
720         final BasicHttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, 200, "OK");
721         state.setResponse(response);
722         this.connContext.setAttribute(HttpAsyncRequestExecutor.HTTP_EXCHANGE_STATE, state);
723         this.connContext.setAttribute(HttpAsyncRequestExecutor.HTTP_HANDLER, this.exchangeHandler);
724         Mockito.when(this.exchangeHandler.isDone()).thenReturn(Boolean.TRUE);
725 
726         Assert.assertEquals("request state: READY; request: GET / HTTP/1.1; " +
727                 "response state: READY; response: HTTP/1.1 200 OK; valid: true;",
728                 state.toString());
729 
730         this.protocolHandler.requestReady(this.conn);
731 
732         Assert.assertEquals(MessageState.READY, state.getRequestState());
733         Assert.assertEquals(MessageState.READY, state.getResponseState());
734     }
735 
736 }