1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28 package org.apache.http.nio.protocol;
29
30 import java.util.concurrent.ExecutionException;
31 import java.util.concurrent.Future;
32
33 import org.apache.http.ConnectionClosedException;
34 import org.apache.http.ConnectionReuseStrategy;
35 import org.apache.http.HttpHost;
36 import org.apache.http.concurrent.FutureCallback;
37 import org.apache.http.impl.nio.pool.BasicNIOPoolEntry;
38 import org.apache.http.nio.NHttpClientConnection;
39 import org.apache.http.nio.protocol.HttpAsyncRequester.ConnRequestCallback;
40 import org.apache.http.pool.ConnPool;
41 import org.apache.http.pool.PoolEntry;
42 import org.apache.http.protocol.BasicHttpContext;
43 import org.apache.http.protocol.HttpContext;
44 import org.apache.http.protocol.HttpProcessor;
45 import org.junit.After;
46 import org.junit.Assert;
47 import org.junit.Before;
48 import org.junit.Test;
49 import org.mockito.ArgumentCaptor;
50 import org.mockito.Matchers;
51 import org.mockito.Mockito;
52
53 public class TestHttpAsyncRequester {
54
55 private HttpProcessor httpProcessor;
56 private ConnectionReuseStrategy reuseStrategy;
57 private HttpAsyncRequester requester;
58 private HttpContext exchangeContext;
59 private HttpContext connContext;
60 private HttpAsyncRequestProducer requestProducer;
61 private HttpAsyncResponseConsumer<Object> responseConsumer;
62 private NHttpClientConnection conn;
63 private FutureCallback<Object> callback;
64 private ConnPool<HttpHost, PoolEntry<HttpHost, NHttpClientConnection>> connPool;
65
66 @Before
67 public void setUp() throws Exception {
68 this.httpProcessor = Mockito.mock(HttpProcessor.class);
69 this.reuseStrategy = Mockito.mock(ConnectionReuseStrategy.class);
70 this.requester = new HttpAsyncRequester(this.httpProcessor, this.reuseStrategy);
71 this.exchangeContext = new BasicHttpContext();
72 this.requestProducer = Mockito.mock(HttpAsyncRequestProducer.class);
73 this.responseConsumer = Mockito.mock(HttpAsyncResponseConsumer.class);
74 this.conn = Mockito.mock(NHttpClientConnection.class);
75 this.callback = Mockito.mock(FutureCallback.class);
76 this.connContext = new BasicHttpContext();
77 this.connPool = Mockito.mock(ConnPool.class);
78
79 Mockito.when(this.conn.getContext()).thenReturn(this.connContext);
80 }
81
82 @After
83 public void tearDown() throws Exception {
84 }
85
86 @Test
87 public void testInvalidExecution() throws Exception {
88 try {
89 this.requester.execute(
90 null,
91 this.responseConsumer,
92 this.conn);
93 Assert.fail("IllegalArgumentException expected");
94 } catch (final IllegalArgumentException ex) {
95 }
96 try {
97 this.requester.execute(
98 this.requestProducer,
99 null,
100 this.conn);
101 Assert.fail("IllegalArgumentException expected");
102 } catch (final IllegalArgumentException ex) {
103 }
104 try {
105 this.requester.execute(
106 this.requestProducer,
107 this.responseConsumer,
108 (NHttpClientConnection) null);
109 Assert.fail("IllegalArgumentException expected");
110 } catch (final IllegalArgumentException ex) {
111 }
112 try {
113 this.requester.execute(
114 this.requestProducer,
115 this.responseConsumer,
116 this.conn,
117 null);
118 Assert.fail("IllegalArgumentException expected");
119 } catch (final IllegalArgumentException ex) {
120 }
121
122 try {
123 this.requester.execute(
124 null,
125 this.responseConsumer,
126 this.connPool);
127 Assert.fail("IllegalArgumentException expected");
128 } catch (final IllegalArgumentException ex) {
129 }
130 try {
131 this.requester.execute(
132 this.requestProducer,
133 null,
134 this.connPool);
135 Assert.fail("IllegalArgumentException expected");
136 } catch (final IllegalArgumentException ex) {
137 }
138 try {
139 this.requester.execute(
140 this.requestProducer,
141 this.responseConsumer,
142 (ConnPool<HttpHost, PoolEntry<HttpHost, NHttpClientConnection>>) null);
143 Assert.fail("IllegalArgumentException expected");
144 } catch (final IllegalArgumentException ex) {
145 }
146 try {
147 this.requester.execute(
148 this.requestProducer,
149 this.responseConsumer,
150 this.connPool,
151 null);
152 Assert.fail("IllegalArgumentException expected");
153 } catch (final IllegalArgumentException ex) {
154 }
155 }
156
157 @Test
158 public void testSimpleExecute() throws Exception {
159 Mockito.when(this.conn.isOpen()).thenReturn(Boolean.TRUE);
160 final Future<Object> future = this.requester.execute(
161 this.requestProducer,
162 this.responseConsumer,
163 this.conn, this.exchangeContext, null);
164 Assert.assertNotNull(future);
165 Assert.assertNotNull(this.connContext.getAttribute(HttpAsyncRequestExecutor.HTTP_HANDLER));
166 Mockito.verify(this.conn).requestOutput();
167 }
168
169 @Test
170 public void testExecuteConnectionClosedUnexpectedly() throws Exception {
171 Mockito.when(this.conn.isOpen()).thenReturn(false);
172 final Future<Object> future = this.requester.execute(
173 this.requestProducer,
174 this.responseConsumer,
175 this.conn, this.exchangeContext, null);
176 Assert.assertNotNull(future);
177 Mockito.verify(this.requestProducer).failed(Matchers.any(ConnectionClosedException.class));
178 Mockito.verify(this.responseConsumer).failed(Matchers.any(ConnectionClosedException.class));
179 Mockito.verify(this.requestProducer, Mockito.atLeastOnce()).close();
180 Mockito.verify(this.responseConsumer, Mockito.atLeastOnce()).close();
181 Assert.assertTrue(future.isDone());
182 Assert.assertNotNull(future.isDone());
183 try {
184 future.get();
185 } catch (final ExecutionException ex) {
186 final Throwable cause = ex.getCause();
187 Assert.assertNotNull(cause);
188 Assert.assertTrue(cause instanceof ConnectionClosedException);
189 }
190
191 }
192
193 @SuppressWarnings({ "rawtypes" })
194 @Test
195 public void testPooledConnectionRequestFailed() throws Exception {
196 final HttpHost host = new HttpHost("somehost");
197 Mockito.when(this.requestProducer.getTarget()).thenReturn(host);
198
199 final Future<Object> future = this.requester.execute(
200 this.requestProducer,
201 this.responseConsumer,
202 this.connPool, this.exchangeContext, this.callback);
203 Assert.assertNotNull(future);
204 final ArgumentCaptor<FutureCallback> argCaptor = ArgumentCaptor.forClass(FutureCallback.class);
205 Mockito.verify(this.connPool).lease(
206 Matchers.eq(host), Matchers.isNull(), argCaptor.capture());
207 final ConnRequestCallback connRequestCallback = (ConnRequestCallback) argCaptor.getValue();
208
209 final Exception oppsie = new Exception();
210 connRequestCallback.failed(oppsie);
211 Mockito.verify(this.responseConsumer).failed(oppsie);
212 Mockito.verify(this.callback).failed(oppsie);
213 Mockito.verify(this.responseConsumer).close();
214 Mockito.verify(this.requestProducer).close();
215 }
216
217 @SuppressWarnings({ "rawtypes" })
218 @Test
219 public void testPooledConnectionRequestCancelled() throws Exception {
220 final HttpHost host = new HttpHost("somehost");
221 Mockito.when(this.requestProducer.getTarget()).thenReturn(host);
222
223 final Future<Object> future = this.requester.execute(
224 this.requestProducer,
225 this.responseConsumer,
226 this.connPool, this.exchangeContext, this.callback);
227 Assert.assertNotNull(future);
228 final ArgumentCaptor<FutureCallback> argCaptor = ArgumentCaptor.forClass(FutureCallback.class);
229 Mockito.verify(this.connPool).lease(
230 Matchers.eq(host), Matchers.isNull(), argCaptor.capture());
231 final ConnRequestCallback connRequestCallback = (ConnRequestCallback) argCaptor.getValue();
232
233 connRequestCallback.cancelled();
234 Mockito.verify(this.responseConsumer).cancel();
235 Mockito.verify(this.callback).cancelled();
236 Mockito.verify(this.responseConsumer).close();
237 Mockito.verify(this.requestProducer).close();
238 }
239
240 @SuppressWarnings({ "rawtypes", "unchecked" })
241 @Test
242 public void testPooledConnectionAutoReleaseOnRequestCancel() throws Exception {
243 final HttpHost host = new HttpHost("somehost");
244 Mockito.when(this.requestProducer.getTarget()).thenReturn(host);
245
246 final Future<Object> future = this.requester.execute(
247 this.requestProducer,
248 this.responseConsumer,
249 this.connPool, this.exchangeContext, this.callback);
250 Assert.assertNotNull(future);
251 final ArgumentCaptor<FutureCallback> argCaptor = ArgumentCaptor.forClass(FutureCallback.class);
252 Mockito.verify(this.connPool).lease(
253 Matchers.eq(host), Matchers.isNull(), argCaptor.capture());
254 final ConnRequestCallback connRequestCallback = (ConnRequestCallback) argCaptor.getValue();
255
256 future.cancel(true);
257 final BasicNIOPoolEntry entry = new BasicNIOPoolEntry("id", host, this.conn);
258 connRequestCallback.completed(entry);
259 Mockito.verify(this.connPool).release(entry, true);
260 Mockito.verify(this.conn, Mockito.never()).requestOutput();
261 }
262
263
264 @SuppressWarnings({ "rawtypes", "unchecked" })
265 @Test
266 public void testPooledRequestExecutionSucceeded() throws Exception {
267 final HttpHost host = new HttpHost("somehost");
268 Mockito.when(this.requestProducer.getTarget()).thenReturn(host);
269 Mockito.when(this.conn.isOpen()).thenReturn(true);
270
271 final Future<Object> future = this.requester.execute(
272 this.requestProducer,
273 this.responseConsumer,
274 this.connPool, this.exchangeContext, this.callback);
275 Assert.assertNotNull(future);
276 final ArgumentCaptor<FutureCallback> argCaptor = ArgumentCaptor.forClass(FutureCallback.class);
277 Mockito.verify(this.connPool).lease(
278 Matchers.eq(host), Matchers.isNull(), argCaptor.capture());
279 final ConnRequestCallback connRequestCallback = (ConnRequestCallback) argCaptor.getValue();
280
281 final BasicNIOPoolEntry entry = new BasicNIOPoolEntry("id", host, this.conn);
282 connRequestCallback.completed(entry);
283 final BasicAsyncClientExchangeHandler exchangeHandler = (BasicAsyncClientExchangeHandler) this.connContext.getAttribute(
284 HttpAsyncRequestExecutor.HTTP_HANDLER);
285 Assert.assertNotNull(exchangeHandler);
286 Mockito.verify(this.conn).requestOutput();
287
288 final Object result = new Object();
289 Mockito.when(this.responseConsumer.getResult()).thenReturn(result);
290 exchangeHandler.responseCompleted();
291 Mockito.verify(this.callback).completed(result);
292 Mockito.verify(this.responseConsumer).close();
293 Mockito.verify(this.requestProducer).close();
294 Mockito.verify(this.connPool).release(entry, true);
295 }
296
297 @SuppressWarnings({ "rawtypes", "unchecked" })
298 @Test
299 public void testPooledRequestExecutionFailed() throws Exception {
300 final HttpHost host = new HttpHost("somehost");
301 Mockito.when(this.requestProducer.getTarget()).thenReturn(host);
302 Mockito.when(this.conn.isOpen()).thenReturn(true);
303
304 final Future<Object> future = this.requester.execute(
305 this.requestProducer,
306 this.responseConsumer,
307 this.connPool, this.exchangeContext, this.callback);
308 Assert.assertNotNull(future);
309 final ArgumentCaptor<FutureCallback> argCaptor = ArgumentCaptor.forClass(FutureCallback.class);
310 Mockito.verify(this.connPool).lease(
311 Matchers.eq(host), Matchers.isNull(), argCaptor.capture());
312 final ConnRequestCallback connRequestCallback = (ConnRequestCallback) argCaptor.getValue();
313
314 final BasicNIOPoolEntry entry = new BasicNIOPoolEntry("id", host, this.conn);
315 connRequestCallback.completed(entry);
316 final BasicAsyncClientExchangeHandler exchangeHandler = (BasicAsyncClientExchangeHandler) this.connContext.getAttribute(
317 HttpAsyncRequestExecutor.HTTP_HANDLER);
318 Assert.assertNotNull(exchangeHandler);
319 Mockito.verify(this.conn).requestOutput();
320
321 final Exception oppsie = new Exception();
322 exchangeHandler.failed(oppsie);
323 Mockito.verify(this.responseConsumer).failed(oppsie);
324 Mockito.verify(this.callback).failed(oppsie);
325 Mockito.verify(this.responseConsumer).close();
326 Mockito.verify(this.requestProducer).close();
327 Mockito.verify(this.connPool).release(entry, false);
328 }
329
330 @SuppressWarnings({ "rawtypes", "unchecked" })
331 @Test
332 public void testPooledRequestExecutionCancelled() throws Exception {
333 final HttpHost host = new HttpHost("somehost");
334 Mockito.when(this.requestProducer.getTarget()).thenReturn(host);
335 Mockito.when(this.conn.isOpen()).thenReturn(true);
336
337 final Future<Object> future = this.requester.execute(
338 this.requestProducer,
339 this.responseConsumer,
340 this.connPool, this.exchangeContext, this.callback);
341 Assert.assertNotNull(future);
342 final ArgumentCaptor<FutureCallback> argCaptor = ArgumentCaptor.forClass(FutureCallback.class);
343 Mockito.verify(this.connPool).lease(
344 Matchers.eq(host), Matchers.isNull(), argCaptor.capture());
345 final ConnRequestCallback connRequestCallback = (ConnRequestCallback) argCaptor.getValue();
346
347 final BasicNIOPoolEntry entry = new BasicNIOPoolEntry("id", host, this.conn);
348 connRequestCallback.completed(entry);
349 final BasicAsyncClientExchangeHandler exchangeHandler = (BasicAsyncClientExchangeHandler) this.connContext.getAttribute(
350 HttpAsyncRequestExecutor.HTTP_HANDLER);
351 Assert.assertNotNull(exchangeHandler);
352 Mockito.verify(this.conn).requestOutput();
353
354 exchangeHandler.cancel();
355 Mockito.verify(this.responseConsumer).cancel();
356 Mockito.verify(this.callback).cancelled();
357 Mockito.verify(this.responseConsumer).close();
358 Mockito.verify(this.requestProducer).close();
359 Mockito.verify(this.connPool).release(entry, false);
360 }
361
362 }