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 package org.apache.http.impl.execchain;
28
29 import java.io.ByteArrayInputStream;
30 import java.io.IOException;
31 import java.io.InterruptedIOException;
32 import java.util.concurrent.ExecutionException;
33 import java.util.concurrent.TimeUnit;
34
35 import org.apache.http.ConnectionReuseStrategy;
36 import org.apache.http.HttpClientConnection;
37 import org.apache.http.HttpException;
38 import org.apache.http.HttpHost;
39 import org.apache.http.HttpRequest;
40 import org.apache.http.HttpResponse;
41 import org.apache.http.HttpVersion;
42 import org.apache.http.client.config.RequestConfig;
43 import org.apache.http.client.entity.EntityBuilder;
44 import org.apache.http.client.methods.CloseableHttpResponse;
45 import org.apache.http.client.methods.HttpExecutionAware;
46 import org.apache.http.client.methods.HttpGet;
47 import org.apache.http.client.methods.HttpRequestWrapper;
48 import org.apache.http.client.protocol.HttpClientContext;
49 import org.apache.http.concurrent.Cancellable;
50 import org.apache.http.conn.ConnectionKeepAliveStrategy;
51 import org.apache.http.conn.ConnectionRequest;
52 import org.apache.http.conn.HttpClientConnectionManager;
53 import org.apache.http.conn.routing.HttpRoute;
54 import org.apache.http.impl.conn.ConnectionShutdownException;
55 import org.apache.http.message.BasicHttpResponse;
56 import org.apache.http.protocol.HttpRequestExecutor;
57 import org.junit.Assert;
58 import org.junit.Before;
59 import org.junit.Test;
60 import org.mockito.ArgumentCaptor;
61 import org.mockito.Mock;
62 import org.mockito.Mockito;
63 import org.mockito.MockitoAnnotations;
64
65 @SuppressWarnings({"boxing","static-access"})
66 public class TestMinimalClientExec {
67
68 @Mock
69 private HttpRequestExecutor requestExecutor;
70 @Mock
71 private HttpClientConnectionManager connManager;
72 @Mock
73 private ConnectionReuseStrategy reuseStrategy;
74 @Mock
75 private ConnectionKeepAliveStrategy keepAliveStrategy;
76 @Mock
77 private HttpExecutionAware execAware;
78 @Mock
79 private ConnectionRequest connRequest;
80 @Mock
81 private HttpClientConnection managedConn;
82
83 private MinimalClientExec minimalClientExec;
84 private HttpHost target;
85
86 @Before
87 public void setup() throws Exception {
88 MockitoAnnotations.initMocks(this);
89 minimalClientExec = new MinimalClientExec(
90 requestExecutor, connManager, reuseStrategy, keepAliveStrategy);
91 target = new HttpHost("foo", 80);
92
93 Mockito.when(connManager.requestConnection(
94 Mockito.<HttpRoute>any(), Mockito.any())).thenReturn(connRequest);
95 Mockito.when(connRequest.get(
96 Mockito.anyLong(), Mockito.<TimeUnit>any())).thenReturn(managedConn);
97 }
98
99 @Test
100 public void testExecRequestNonPersistentConnection() throws Exception {
101 final HttpRoute route = new HttpRoute(target);
102 final HttpClientContext context = new HttpClientContext();
103 final RequestConfig config = RequestConfig.custom()
104 .setConnectTimeout(123)
105 .setSocketTimeout(234)
106 .setConnectionRequestTimeout(345)
107 .build();
108 context.setRequestConfig(config);
109 final HttpRequestWrapper request = HttpRequestWrapper.wrap(new HttpGet("http://bar/test"));
110 final HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, 200, "OK");
111 Mockito.when(requestExecutor.execute(
112 Mockito.same(request),
113 Mockito.<HttpClientConnection>any(),
114 Mockito.<HttpClientContext>any())).thenReturn(response);
115
116 final CloseableHttpResponse finalResponse = minimalClientExec.execute(
117 route, request, context, execAware);
118 Mockito.verify(connManager).requestConnection(route, null);
119 Mockito.verify(connRequest).get(345, TimeUnit.MILLISECONDS);
120 Mockito.verify(execAware, Mockito.times(1)).setCancellable(connRequest);
121 Mockito.verify(execAware, Mockito.times(2)).setCancellable(Mockito.<Cancellable>any());
122 Mockito.verify(connManager).connect(managedConn, route, 123, context);
123 Mockito.verify(connManager).routeComplete(managedConn, route, context);
124 Mockito.verify(managedConn).setSocketTimeout(234);
125 Mockito.verify(requestExecutor, Mockito.times(1)).execute(request, managedConn, context);
126 Mockito.verify(managedConn, Mockito.times(1)).close();
127 Mockito.verify(connManager).releaseConnection(managedConn, null, 0, TimeUnit.MILLISECONDS);
128
129 Assert.assertSame(managedConn, context.getConnection());
130 Assert.assertNotNull(finalResponse);
131 Assert.assertTrue(finalResponse instanceof HttpResponseProxy);
132 }
133
134 @Test
135 public void testExecRequestPersistentConnection() throws Exception {
136 final HttpRoute route = new HttpRoute(target);
137 final HttpClientContext context = new HttpClientContext();
138 final HttpRequestWrapper request = HttpRequestWrapper.wrap(new HttpGet("http://bar/test"));
139 final HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, 200, "OK");
140
141 Mockito.when(managedConn.isOpen()).thenReturn(Boolean.TRUE);
142 Mockito.when(managedConn.isStale()).thenReturn(Boolean.FALSE);
143 Mockito.when(requestExecutor.execute(
144 Mockito.same(request),
145 Mockito.<HttpClientConnection>any(),
146 Mockito.<HttpClientContext>any())).thenReturn(response);
147 Mockito.when(reuseStrategy.keepAlive(
148 Mockito.same(response),
149 Mockito.<HttpClientContext>any())).thenReturn(Boolean.TRUE);
150 Mockito.when(keepAliveStrategy.getKeepAliveDuration(
151 Mockito.same(response),
152 Mockito.<HttpClientContext>any())).thenReturn(678L);
153
154 final CloseableHttpResponse finalResponse = minimalClientExec.execute(
155 route, request, context, execAware);
156 Mockito.verify(connManager).requestConnection(route, null);
157 Mockito.verify(connRequest).get(0, TimeUnit.MILLISECONDS);
158 Mockito.verify(requestExecutor, Mockito.times(1)).execute(request, managedConn, context);
159 Mockito.verify(connManager).releaseConnection(managedConn, null, 678L, TimeUnit.MILLISECONDS);
160 Mockito.verify(managedConn, Mockito.never()).close();
161
162 Assert.assertNotNull(finalResponse);
163 Assert.assertTrue(finalResponse instanceof HttpResponseProxy);
164 }
165
166 @Test
167 public void testExecRequestConnectionRelease() throws Exception {
168 final HttpRoute route = new HttpRoute(target);
169 final HttpClientContext context = new HttpClientContext();
170 final HttpRequestWrapper request = HttpRequestWrapper.wrap(new HttpGet("http://bar/test"));
171 final HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, 200, "OK");
172
173 response.setEntity(EntityBuilder.create()
174 .setStream(new ByteArrayInputStream(new byte[]{}))
175 .build());
176
177 Mockito.when(managedConn.isOpen()).thenReturn(Boolean.TRUE);
178 Mockito.when(managedConn.isStale()).thenReturn(Boolean.FALSE);
179 Mockito.when(requestExecutor.execute(
180 Mockito.same(request),
181 Mockito.<HttpClientConnection>any(),
182 Mockito.<HttpClientContext>any())).thenReturn(response);
183 Mockito.when(reuseStrategy.keepAlive(
184 Mockito.same(response),
185 Mockito.<HttpClientContext>any())).thenReturn(Boolean.FALSE);
186
187 final CloseableHttpResponse finalResponse = minimalClientExec.execute(
188 route, request, context, execAware);
189 Mockito.verify(connManager).requestConnection(route, null);
190 Mockito.verify(connRequest).get(0, TimeUnit.MILLISECONDS);
191 Mockito.verify(requestExecutor, Mockito.times(1)).execute(request, managedConn, context);
192 Mockito.verify(connManager, Mockito.never()).releaseConnection(
193 Mockito.same(managedConn),
194 Mockito.any(),
195 Mockito.anyInt(),
196 Mockito.<TimeUnit>any());
197 Mockito.verify(managedConn, Mockito.never()).close();
198
199 Assert.assertNotNull(finalResponse);
200 Assert.assertTrue(finalResponse instanceof HttpResponseProxy);
201 finalResponse.close();
202
203 Mockito.verify(connManager, Mockito.times(1)).releaseConnection(
204 managedConn, null, 0, TimeUnit.MILLISECONDS);
205 Mockito.verify(managedConn, Mockito.times(1)).close();
206 }
207
208 @Test
209 public void testSocketTimeoutExistingConnection() throws Exception {
210 final HttpRoute route = new HttpRoute(target);
211 final HttpClientContext context = new HttpClientContext();
212 final RequestConfig config = RequestConfig.custom().setSocketTimeout(3000).build();
213 final HttpRequestWrapper request = HttpRequestWrapper.wrap(new HttpGet("http://bar/test"));
214 context.setRequestConfig(config);
215 final HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, 200, "OK");
216 Mockito.when(managedConn.isOpen()).thenReturn(true);
217 Mockito.when(requestExecutor.execute(
218 Mockito.same(request),
219 Mockito.<HttpClientConnection>any(),
220 Mockito.<HttpClientContext>any())).thenReturn(response);
221
222 minimalClientExec.execute(route, request, context, execAware);
223 Mockito.verify(managedConn).setSocketTimeout(3000);
224 }
225
226 @Test
227 public void testSocketTimeoutReset() throws Exception {
228 final HttpRoute route = new HttpRoute(target);
229 final HttpClientContext context = new HttpClientContext();
230 final HttpRequestWrapper request = HttpRequestWrapper.wrap(new HttpGet("http://bar/test"));
231 final HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, 200, "OK");
232 Mockito.when(managedConn.isOpen()).thenReturn(Boolean.TRUE);
233 Mockito.when(requestExecutor.execute(
234 Mockito.same(request),
235 Mockito.<HttpClientConnection>any(),
236 Mockito.<HttpClientContext>any())).thenReturn(response);
237
238 minimalClientExec.execute(route, request, context, execAware);
239 Mockito.verify(managedConn, Mockito.never()).setSocketTimeout(Mockito.anyInt());
240 }
241
242 @Test(expected=RequestAbortedException.class)
243 public void testExecAbortedPriorToConnectionLease() throws Exception {
244 final HttpRoute route = new HttpRoute(target);
245 final HttpClientContext context = new HttpClientContext();
246 final HttpRequestWrapper request = HttpRequestWrapper.wrap(new HttpGet("http://bar/test"));
247
248 Mockito.when(managedConn.isOpen()).thenReturn(Boolean.FALSE);
249 Mockito.when(execAware.isAborted()).thenReturn(Boolean.TRUE);
250 try {
251 minimalClientExec.execute(route, request, context, execAware);
252 } catch (final IOException ex) {
253 Mockito.verify(connRequest, Mockito.times(1)).cancel();
254 throw ex;
255 }
256 }
257
258 @Test(expected=RequestAbortedException.class)
259 public void testExecConnectionRequestFailed() throws Exception {
260 final HttpRoute route = new HttpRoute(target);
261 final HttpClientContext context = new HttpClientContext();
262 final HttpRequestWrapper request = HttpRequestWrapper.wrap(new HttpGet("http://bar/test"));
263
264 Mockito.when(connRequest.get(Mockito.anyInt(), Mockito.<TimeUnit>any()))
265 .thenThrow(new ExecutionException("Opppsie", null));
266 minimalClientExec.execute(route, request, context, execAware);
267 }
268
269 @Test(expected=InterruptedIOException.class)
270 public void testExecConnectionShutDown() throws Exception {
271 final HttpRoute route = new HttpRoute(target);
272 final HttpClientContext context = new HttpClientContext();
273 final HttpRequestWrapper request = HttpRequestWrapper.wrap(new HttpGet("http://bar/test"));
274
275 Mockito.when(requestExecutor.execute(
276 Mockito.<HttpRequest>any(),
277 Mockito.<HttpClientConnection>any(),
278 Mockito.<HttpClientContext>any())).thenThrow(new ConnectionShutdownException());
279
280 minimalClientExec.execute(route, request, context, execAware);
281 }
282
283 @Test(expected=RuntimeException.class)
284 public void testExecRuntimeException() throws Exception {
285 final HttpRoute route = new HttpRoute(target);
286 final HttpClientContext context = new HttpClientContext();
287 final HttpRequestWrapper request = HttpRequestWrapper.wrap(new HttpGet("http://bar/test"));
288
289 Mockito.when(requestExecutor.execute(
290 Mockito.<HttpRequest>any(),
291 Mockito.<HttpClientConnection>any(),
292 Mockito.<HttpClientContext>any())).thenThrow(new RuntimeException("Ka-boom"));
293
294 try {
295 minimalClientExec.execute(route, request, context, execAware);
296 } catch (final Exception ex) {
297 Mockito.verify(connManager).releaseConnection(managedConn, null, 0, TimeUnit.MILLISECONDS);
298
299 throw ex;
300 }
301 }
302
303 @Test(expected=HttpException.class)
304 public void testExecHttpException() throws Exception {
305 final HttpRoute route = new HttpRoute(target);
306 final HttpClientContext context = new HttpClientContext();
307 final HttpRequestWrapper request = HttpRequestWrapper.wrap(new HttpGet("http://bar/test"));
308
309 Mockito.when(requestExecutor.execute(
310 Mockito.<HttpRequest>any(),
311 Mockito.<HttpClientConnection>any(),
312 Mockito.<HttpClientContext>any())).thenThrow(new HttpException("Ka-boom"));
313
314 try {
315 minimalClientExec.execute(route, request, context, execAware);
316 } catch (final Exception ex) {
317 Mockito.verify(connManager).releaseConnection(managedConn, null, 0, TimeUnit.MILLISECONDS);
318
319 throw ex;
320 }
321 }
322
323 @Test(expected=IOException.class)
324 public void testExecIOException() throws Exception {
325 final HttpRoute route = new HttpRoute(target);
326 final HttpClientContext context = new HttpClientContext();
327 final HttpRequestWrapper request = HttpRequestWrapper.wrap(new HttpGet("http://bar/test"));
328
329 Mockito.when(requestExecutor.execute(
330 Mockito.<HttpRequest>any(),
331 Mockito.<HttpClientConnection>any(),
332 Mockito.<HttpClientContext>any())).thenThrow(new IOException("Ka-boom"));
333
334 try {
335 minimalClientExec.execute(route, request, context, execAware);
336 } catch (final Exception ex) {
337 Mockito.verify(connManager).releaseConnection(managedConn, null, 0, TimeUnit.MILLISECONDS);
338
339 throw ex;
340 }
341 }
342
343 @Test
344 public void absoluteUriIsRewrittenToRelativeBeforeBeingPassedInRequestLine() throws Exception {
345 final HttpRoute route = new HttpRoute(target);
346 final HttpClientContext context = new HttpClientContext();
347 final HttpRequestWrapper request = HttpRequestWrapper.wrap(new HttpGet("http://bar/test"));
348
349 final HttpResponse response = Mockito.mock(HttpResponse.class);
350 Mockito.when(requestExecutor.execute(
351 Mockito.<HttpRequest>any(),
352 Mockito.<HttpClientConnection>any(),
353 Mockito.<HttpClientContext>any())).thenReturn(response);
354
355 minimalClientExec.execute(route, request, context, execAware);
356
357 final ArgumentCaptor<HttpRequest> reqCaptor = ArgumentCaptor.forClass(HttpRequest.class);
358 Mockito.verify(requestExecutor).execute(reqCaptor.capture(), Mockito.<HttpClientConnection>any(), Mockito.<HttpClientContext>any());
359
360 Assert.assertEquals("/test", reqCaptor.getValue().getRequestLine().getUri());
361 }
362 }