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.impl.conn;
29
30 import java.net.InetAddress;
31 import java.net.InetSocketAddress;
32 import java.net.Socket;
33 import java.util.concurrent.TimeUnit;
34
35 import org.apache.http.HttpClientConnection;
36 import org.apache.http.HttpHost;
37 import org.apache.http.client.protocol.HttpClientContext;
38 import org.apache.http.config.ConnectionConfig;
39 import org.apache.http.config.Lookup;
40 import org.apache.http.config.SocketConfig;
41 import org.apache.http.conn.ConnectionRequest;
42 import org.apache.http.conn.DnsResolver;
43 import org.apache.http.conn.HttpConnectionFactory;
44 import org.apache.http.conn.ManagedHttpClientConnection;
45 import org.apache.http.conn.SchemePortResolver;
46 import org.apache.http.conn.routing.HttpRoute;
47 import org.apache.http.conn.socket.ConnectionSocketFactory;
48 import org.apache.http.conn.socket.LayeredConnectionSocketFactory;
49 import org.apache.http.protocol.HttpContext;
50 import org.junit.Assert;
51 import org.junit.Before;
52 import org.junit.Test;
53 import org.mockito.Mock;
54 import org.mockito.Mockito;
55 import org.mockito.MockitoAnnotations;
56
57 @SuppressWarnings({"boxing","static-access"})
58 public class TestBasicHttpClientConnectionManager {
59
60 @Mock
61 private ManagedHttpClientConnection conn;
62 @Mock
63 private HttpConnectionFactory<HttpRoute, ManagedHttpClientConnection> connFactory;
64 @Mock
65 private Lookup<ConnectionSocketFactory> socketFactoryRegistry;
66 @Mock
67 private ConnectionSocketFactory plainSocketFactory;
68 @Mock
69 private LayeredConnectionSocketFactory sslSocketFactory;
70 @Mock
71 private Socket socket;
72 @Mock
73 private SchemePortResolver schemePortResolver;
74 @Mock
75 private DnsResolver dnsResolver;
76
77 private BasicHttpClientConnectionManager mgr;
78
79 @Before
80 public void setup() throws Exception {
81 MockitoAnnotations.initMocks(this);
82 mgr = new BasicHttpClientConnectionManager(
83 socketFactoryRegistry, connFactory, schemePortResolver, dnsResolver);
84 }
85
86 @Test
87 public void testLeaseReleaseNonReusable() throws Exception {
88 final HttpHost target = new HttpHost("localhost", 80);
89 final HttpRoute route = new HttpRoute(target);
90
91 Mockito.when(connFactory.create(
92 Mockito.eq(route), Mockito.<ConnectionConfig>any())).thenReturn(conn);
93
94 final ConnectionRequest connRequest1 = mgr.requestConnection(route, null);
95 final HttpClientConnection conn1 = connRequest1.get(0, TimeUnit.MILLISECONDS);
96 Assert.assertNotNull(conn1);
97 Assert.assertFalse(conn1.isOpen());
98
99 mgr.releaseConnection(conn1, null, 100, TimeUnit.MILLISECONDS);
100
101 Assert.assertNull(mgr.getRoute());
102 Assert.assertNull(mgr.getState());
103
104 final ConnectionRequest connRequest2 = mgr.requestConnection(route, null);
105 final HttpClientConnection conn2 = connRequest2.get(0, TimeUnit.MILLISECONDS);
106 Assert.assertNotNull(conn2);
107 Assert.assertFalse(conn2.isOpen());
108
109 Mockito.verify(connFactory, Mockito.times(2)).create(
110 Mockito.eq(route), Mockito.<ConnectionConfig>any());
111 }
112
113 @Test
114 public void testLeaseReleaseReusable() throws Exception {
115 final HttpHost target = new HttpHost("somehost", 80);
116 final HttpRoute route = new HttpRoute(target);
117
118 Mockito.when(connFactory.create(Mockito.eq(route), Mockito.<ConnectionConfig>any())).thenReturn(conn);
119
120 final ConnectionRequest connRequest1 = mgr.requestConnection(route, null);
121 final HttpClientConnection conn1 = connRequest1.get(0, TimeUnit.MILLISECONDS);
122 Assert.assertNotNull(conn1);
123
124 Mockito.verify(connFactory, Mockito.times(1)).create(
125 Mockito.eq(route), Mockito.<ConnectionConfig>any());
126
127 Mockito.when(conn.isOpen()).thenReturn(Boolean.TRUE);
128
129 mgr.releaseConnection(conn1, null, 10000, TimeUnit.MILLISECONDS);
130
131 Assert.assertEquals(route, mgr.getRoute());
132 Assert.assertEquals(null, mgr.getState());
133
134 final ConnectionRequest connRequest2 = mgr.requestConnection(route, null);
135 final HttpClientConnection conn2 = connRequest2.get(0, TimeUnit.MILLISECONDS);
136 Assert.assertNotNull(conn2);
137 Assert.assertTrue(conn2.isOpen());
138
139 Mockito.verify(connFactory, Mockito.times(1)).create(
140 Mockito.eq(route), Mockito.<ConnectionConfig>any());
141 }
142
143 @Test
144 public void testLeaseReleaseReusableWithState() throws Exception {
145 final HttpHost target = new HttpHost("somehost", 80);
146 final HttpRoute route = new HttpRoute(target);
147
148 Mockito.when(connFactory.create(
149 Mockito.eq(route), Mockito.<ConnectionConfig>any())).thenReturn(conn);
150
151 final ConnectionRequest connRequest1 = mgr.requestConnection(route, "some state");
152 final HttpClientConnection conn1 = connRequest1.get(0, TimeUnit.MILLISECONDS);
153 Assert.assertNotNull(conn1);
154
155 Mockito.verify(connFactory, Mockito.times(1)).create(
156 Mockito.eq(route), Mockito.<ConnectionConfig>any());
157
158 Mockito.when(conn.isOpen()).thenReturn(Boolean.TRUE);
159
160 mgr.releaseConnection(conn1, "some other state", 10000, TimeUnit.MILLISECONDS);
161
162 Assert.assertEquals(route, mgr.getRoute());
163 Assert.assertEquals("some other state", mgr.getState());
164
165 final ConnectionRequest connRequest2 = mgr.requestConnection(route, "some other state");
166 final HttpClientConnection conn2 = connRequest2.get(0, TimeUnit.MILLISECONDS);
167 Assert.assertNotNull(conn2);
168 Assert.assertTrue(conn2.isOpen());
169
170 Mockito.verify(connFactory, Mockito.times(1)).create(
171 Mockito.eq(route), Mockito.<ConnectionConfig>any());
172 }
173
174 @Test
175 public void testLeaseDifferentRoute() throws Exception {
176 final HttpHost target1 = new HttpHost("somehost", 80);
177 final HttpRoute route1 = new HttpRoute(target1);
178
179 Mockito.when(connFactory.create(
180 Mockito.<HttpRoute>any(), Mockito.<ConnectionConfig>any())).thenReturn(conn);
181
182 final ConnectionRequest connRequest1 = mgr.requestConnection(route1, null);
183 final HttpClientConnection conn1 = connRequest1.get(0, TimeUnit.MILLISECONDS);
184 Assert.assertNotNull(conn1);
185
186 Mockito.verify(connFactory, Mockito.times(1)).create(
187 Mockito.eq(route1), Mockito.<ConnectionConfig>any());
188
189 Mockito.when(conn.isOpen()).thenReturn(Boolean.TRUE, Boolean.FALSE);
190
191 mgr.releaseConnection(conn1, null, 0, TimeUnit.MILLISECONDS);
192
193 Assert.assertEquals(route1, mgr.getRoute());
194 Assert.assertEquals(null, mgr.getState());
195
196 final HttpHost target2 = new HttpHost("otherhost", 80);
197 final HttpRoute route2 = new HttpRoute(target2);
198 final ConnectionRequest connRequest2 = mgr.requestConnection(route2, null);
199 final HttpClientConnection conn2 = connRequest2.get(0, TimeUnit.MILLISECONDS);
200 Assert.assertNotNull(conn2);
201 Assert.assertFalse(conn2.isOpen());
202
203 Mockito.verify(conn).close();
204 Mockito.verify(connFactory, Mockito.times(1)).create(
205 Mockito.eq(route1), Mockito.<ConnectionConfig>any());
206 Mockito.verify(connFactory, Mockito.times(1)).create(
207 Mockito.eq(route2), Mockito.<ConnectionConfig>any());
208 }
209
210 @Test
211 public void testLeaseExpired() throws Exception {
212 final HttpHost target = new HttpHost("somehost", 80);
213 final HttpRoute route = new HttpRoute(target);
214
215 Mockito.when(connFactory.create(
216 Mockito.eq(route), Mockito.<ConnectionConfig>any())).thenReturn(conn);
217
218 final ConnectionRequest connRequest1 = mgr.requestConnection(route, null);
219 final HttpClientConnection conn1 = connRequest1.get(0, TimeUnit.MILLISECONDS);
220 Assert.assertNotNull(conn1);
221
222 Mockito.verify(connFactory, Mockito.times(1)).create(
223 Mockito.eq(route), Mockito.<ConnectionConfig>any());
224
225 Mockito.when(conn.isOpen()).thenReturn(Boolean.TRUE, Boolean.FALSE);
226
227 mgr.releaseConnection(conn1, null, 10, TimeUnit.MILLISECONDS);
228
229 Assert.assertEquals(route, mgr.getRoute());
230 Assert.assertEquals(null, mgr.getState());
231
232 Thread.sleep(50);
233
234 final ConnectionRequest connRequest2 = mgr.requestConnection(route, null);
235 final HttpClientConnection conn2 = connRequest2.get(0, TimeUnit.MILLISECONDS);
236 Assert.assertNotNull(conn2);
237 Assert.assertFalse(conn2.isOpen());
238
239 Mockito.verify(conn).close();
240 Mockito.verify(connFactory, Mockito.times(2)).create(
241 Mockito.eq(route), Mockito.<ConnectionConfig>any());
242 }
243
244 @Test(expected=IllegalArgumentException.class)
245 public void testLeaseInvalidArg() throws Exception {
246 mgr.requestConnection(null, null);
247 }
248
249 @Test(expected=IllegalArgumentException.class)
250 public void testReleaseInvalidArg() throws Exception {
251 mgr.releaseConnection(null, null, 0, TimeUnit.MILLISECONDS);
252 }
253
254 @Test(expected=IllegalStateException.class)
255 public void testReleaseAnotherConnection() throws Exception {
256 final HttpClientConnection wrongCon = Mockito.mock(HttpClientConnection.class);
257 mgr.releaseConnection(wrongCon, null, 0, TimeUnit.MILLISECONDS);
258 }
259
260 @Test
261 public void testShutdown() throws Exception {
262 final HttpHost target = new HttpHost("somehost", 80);
263 final HttpRoute route = new HttpRoute(target);
264
265 Mockito.when(connFactory.create(
266 Mockito.eq(route), Mockito.<ConnectionConfig>any())).thenReturn(conn);
267
268 final ConnectionRequest connRequest1 = mgr.requestConnection(route, null);
269 final HttpClientConnection conn1 = connRequest1.get(0, TimeUnit.MILLISECONDS);
270 Assert.assertNotNull(conn1);
271
272 Mockito.verify(connFactory, Mockito.times(1)).create(
273 Mockito.eq(route), Mockito.<ConnectionConfig>any());
274
275 Mockito.when(conn.isOpen()).thenReturn(Boolean.TRUE);
276
277 mgr.releaseConnection(conn1, null, 0, TimeUnit.MILLISECONDS);
278
279 mgr.shutdown();
280
281 Mockito.verify(conn, Mockito.times(1)).shutdown();
282
283 try {
284 final ConnectionRequest connRequest2 = mgr.requestConnection(route, null);
285 connRequest2.get(0, TimeUnit.MILLISECONDS);
286 Assert.fail("IllegalStateException expected");
287 } catch (final IllegalStateException ex) {
288 }
289
290
291 mgr.closeExpiredConnections();
292 mgr.closeIdleConnections(0L, TimeUnit.MILLISECONDS);
293 mgr.shutdown();
294
295 Mockito.verify(conn, Mockito.times(1)).shutdown();
296 }
297
298 @Test
299 public void testCloseExpired() throws Exception {
300 final HttpHost target = new HttpHost("somehost", 80);
301 final HttpRoute route = new HttpRoute(target);
302
303 Mockito.when(connFactory.create(
304 Mockito.eq(route), Mockito.<ConnectionConfig>any())).thenReturn(conn);
305
306 final ConnectionRequest connRequest1 = mgr.requestConnection(route, null);
307 final HttpClientConnection conn1 = connRequest1.get(0, TimeUnit.MILLISECONDS);
308 Assert.assertNotNull(conn1);
309
310 Mockito.verify(connFactory, Mockito.times(1)).create(
311 Mockito.eq(route), Mockito.<ConnectionConfig>any());
312
313 Mockito.when(conn.isOpen()).thenReturn(Boolean.TRUE, Boolean.FALSE);
314
315 mgr.releaseConnection(conn1, null, 10, TimeUnit.MILLISECONDS);
316
317 Assert.assertEquals(route, mgr.getRoute());
318 Assert.assertEquals(null, mgr.getState());
319
320 Thread.sleep(50);
321
322 mgr.closeExpiredConnections();
323
324 Mockito.verify(conn).close();
325 }
326
327 @Test
328 public void testCloseIdle() throws Exception {
329 final HttpHost target = new HttpHost("somehost", 80);
330 final HttpRoute route = new HttpRoute(target);
331
332 Mockito.when(connFactory.create(
333 Mockito.eq(route), Mockito.<ConnectionConfig>any())).thenReturn(conn);
334
335 final ConnectionRequest connRequest1 = mgr.requestConnection(route, null);
336 final HttpClientConnection conn1 = connRequest1.get(0, TimeUnit.MILLISECONDS);
337 Assert.assertNotNull(conn1);
338
339 Mockito.verify(connFactory, Mockito.times(1)).create(
340 Mockito.eq(route), Mockito.<ConnectionConfig>any());
341
342 Mockito.when(conn.isOpen()).thenReturn(Boolean.TRUE, Boolean.FALSE);
343
344 mgr.releaseConnection(conn1, null, 0, TimeUnit.MILLISECONDS);
345
346 Assert.assertEquals(route, mgr.getRoute());
347 Assert.assertEquals(null, mgr.getState());
348
349 Thread.sleep(100);
350
351 mgr.closeIdleConnections(50, TimeUnit.MILLISECONDS);
352
353 Mockito.verify(conn).close();
354 }
355
356 @Test(expected=IllegalStateException.class)
357 public void testAlreadyLeased() throws Exception {
358 final HttpHost target = new HttpHost("somehost", 80);
359 final HttpRoute route = new HttpRoute(target);
360
361 Mockito.when(connFactory.create(
362 Mockito.eq(route), Mockito.<ConnectionConfig>any())).thenReturn(conn);
363
364 final ConnectionRequest connRequest1 = mgr.requestConnection(route, null);
365 final HttpClientConnection conn1 = connRequest1.get(0, TimeUnit.MILLISECONDS);
366 Assert.assertNotNull(conn1);
367 mgr.releaseConnection(conn1, null, 100, TimeUnit.MILLISECONDS);
368
369 mgr.getConnection(route, null);
370 mgr.getConnection(route, null);
371 }
372
373 @Test
374 public void testTargetConnect() throws Exception {
375 final HttpHost target = new HttpHost("somehost", 443, "https");
376 final InetAddress remote = InetAddress.getByAddress(new byte[] {10, 0, 0, 1});
377 final InetAddress local = InetAddress.getByAddress(new byte[] {127, 0, 0, 1});
378 final HttpRoute route = new HttpRoute(target, local, true);
379
380 Mockito.when(connFactory.create(
381 Mockito.eq(route), Mockito.<ConnectionConfig>any())).thenReturn(conn);
382
383 final ConnectionRequest connRequest1 = mgr.requestConnection(route, null);
384 final HttpClientConnection conn1 = connRequest1.get(0, TimeUnit.MILLISECONDS);
385 Assert.assertNotNull(conn1);
386
387 final HttpClientContext context = HttpClientContext.create();
388 final SocketConfig sconfig = SocketConfig.custom().build();
389
390 mgr.setSocketConfig(sconfig);
391
392 Mockito.when(dnsResolver.resolve("somehost")).thenReturn(new InetAddress[] {remote});
393 Mockito.when(schemePortResolver.resolve(target)).thenReturn(8443);
394 Mockito.when(socketFactoryRegistry.lookup("https")).thenReturn(plainSocketFactory);
395 Mockito.when(plainSocketFactory.createSocket(Mockito.<HttpContext>any())).thenReturn(socket);
396 Mockito.when(plainSocketFactory.connectSocket(
397 Mockito.anyInt(),
398 Mockito.eq(socket),
399 Mockito.<HttpHost>any(),
400 Mockito.<InetSocketAddress>any(),
401 Mockito.<InetSocketAddress>any(),
402 Mockito.<HttpContext>any())).thenReturn(socket);
403
404 mgr.connect(conn1, route, 123, context);
405
406 Mockito.verify(dnsResolver, Mockito.times(1)).resolve("somehost");
407 Mockito.verify(schemePortResolver, Mockito.times(1)).resolve(target);
408 Mockito.verify(plainSocketFactory, Mockito.times(1)).createSocket(context);
409 Mockito.verify(plainSocketFactory, Mockito.times(1)).connectSocket(123, socket, target,
410 new InetSocketAddress(remote, 8443),
411 new InetSocketAddress(local, 0), context);
412
413 mgr.routeComplete(conn1, route, context);
414 }
415
416 @Test
417 public void testProxyConnectAndUpgrade() throws Exception {
418 final HttpHost target = new HttpHost("somehost", 443, "https");
419 final HttpHost proxy = new HttpHost("someproxy", 8080);
420 final InetAddress remote = InetAddress.getByAddress(new byte[] {10, 0, 0, 1});
421 final InetAddress local = InetAddress.getByAddress(new byte[] {127, 0, 0, 1});
422 final HttpRoute route = new HttpRoute(target, local, proxy, true);
423
424 Mockito.when(connFactory.create(
425 Mockito.eq(route), Mockito.<ConnectionConfig>any())).thenReturn(conn);
426
427 final ConnectionRequest connRequest1 = mgr.requestConnection(route, null);
428 final HttpClientConnection conn1 = connRequest1.get(0, TimeUnit.MILLISECONDS);
429 Assert.assertNotNull(conn1);
430
431 final HttpClientContext context = HttpClientContext.create();
432 final SocketConfig sconfig = SocketConfig.custom().build();
433
434 mgr.setSocketConfig(sconfig);
435
436 Mockito.when(dnsResolver.resolve("someproxy")).thenReturn(new InetAddress[] {remote});
437 Mockito.when(schemePortResolver.resolve(proxy)).thenReturn(8080);
438 Mockito.when(schemePortResolver.resolve(target)).thenReturn(8443);
439 Mockito.when(socketFactoryRegistry.lookup("http")).thenReturn(plainSocketFactory);
440 Mockito.when(socketFactoryRegistry.lookup("https")).thenReturn(sslSocketFactory);
441 Mockito.when(plainSocketFactory.createSocket(Mockito.<HttpContext>any())).thenReturn(socket);
442 Mockito.when(plainSocketFactory.connectSocket(
443 Mockito.anyInt(),
444 Mockito.eq(socket),
445 Mockito.<HttpHost>any(),
446 Mockito.<InetSocketAddress>any(),
447 Mockito.<InetSocketAddress>any(),
448 Mockito.<HttpContext>any())).thenReturn(socket);
449
450 mgr.connect(conn1, route, 123, context);
451
452 Mockito.verify(dnsResolver, Mockito.times(1)).resolve("someproxy");
453 Mockito.verify(schemePortResolver, Mockito.times(1)).resolve(proxy);
454 Mockito.verify(plainSocketFactory, Mockito.times(1)).createSocket(context);
455 Mockito.verify(plainSocketFactory, Mockito.times(1)).connectSocket(123, socket, proxy,
456 new InetSocketAddress(remote, 8080),
457 new InetSocketAddress(local, 0), context);
458
459 Mockito.when(conn.getSocket()).thenReturn(socket);
460
461 mgr.upgrade(conn1, route, context);
462
463 Mockito.verify(schemePortResolver, Mockito.times(1)).resolve(target);
464 Mockito.verify(sslSocketFactory, Mockito.times(1)).createLayeredSocket(
465 socket, "somehost", 8443, context);
466
467 mgr.routeComplete(conn1, route, context);
468 }
469
470 }