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.ExecutionException;
34 import java.util.concurrent.Future;
35 import java.util.concurrent.TimeUnit;
36 import java.util.concurrent.TimeoutException;
37
38 import org.apache.commons.logging.LogFactory;
39 import org.apache.http.HttpClientConnection;
40 import org.apache.http.HttpHost;
41 import org.apache.http.client.protocol.HttpClientContext;
42 import org.apache.http.config.ConnectionConfig;
43 import org.apache.http.config.Lookup;
44 import org.apache.http.config.SocketConfig;
45 import org.apache.http.conn.ConnectionPoolTimeoutException;
46 import org.apache.http.conn.ConnectionRequest;
47 import org.apache.http.conn.DnsResolver;
48 import org.apache.http.conn.SchemePortResolver;
49 import org.apache.http.conn.ManagedHttpClientConnection;
50 import org.apache.http.conn.routing.HttpRoute;
51 import org.apache.http.conn.socket.ConnectionSocketFactory;
52 import org.apache.http.conn.socket.LayeredConnectionSocketFactory;
53 import org.apache.http.protocol.HttpContext;
54 import org.junit.Assert;
55 import org.junit.Before;
56 import org.junit.Test;
57 import org.mockito.Mock;
58 import org.mockito.Mockito;
59 import org.mockito.MockitoAnnotations;
60
61
62
63
64 @SuppressWarnings({"boxing","static-access","resource"})
65 public class TestPoolingHttpClientConnectionManager {
66
67 @Mock
68 private ManagedHttpClientConnection conn;
69 @Mock
70 private Lookup<ConnectionSocketFactory> socketFactoryRegistry;
71 @Mock
72 private ConnectionSocketFactory plainSocketFactory;
73 @Mock
74 private ConnectionSocketFactory sslSocketFactory;
75 @Mock
76 private Socket socket;
77 @Mock
78 private SchemePortResolver schemePortResolver;
79 @Mock
80 private DnsResolver dnsResolver;
81 @Mock
82 private Future<CPoolEntry> future;
83 @Mock
84 private CPool pool;
85 private PoolingHttpClientConnectionManager mgr;
86
87 @Before
88 public void setup() throws Exception {
89 MockitoAnnotations.initMocks(this);
90 mgr = new PoolingHttpClientConnectionManager(
91 pool, socketFactoryRegistry, schemePortResolver, dnsResolver);
92 }
93
94 @Test
95 public void testLeaseRelease() throws Exception {
96 final HttpHost target = new HttpHost("localhost", 80);
97 final HttpRoute route = new HttpRoute(target);
98
99 final CPoolEntry entry = new CPoolEntry(LogFactory.getLog(getClass()), "id", route, conn,
100 -1, TimeUnit.MILLISECONDS);
101 entry.markRouteComplete();
102
103 Mockito.when(future.isCancelled()).thenReturn(Boolean.FALSE);
104 Mockito.when(socketFactoryRegistry.lookup("http")).thenReturn(plainSocketFactory);
105 Mockito.when(schemePortResolver.resolve(target)).thenReturn(80);
106 Mockito.when(plainSocketFactory.createSocket(Mockito.<HttpContext>any())).thenReturn(socket);
107
108 Mockito.when(conn.isOpen()).thenReturn(true);
109 Mockito.when(future.isCancelled()).thenReturn(false);
110 Mockito.when(future.get(1, TimeUnit.SECONDS)).thenReturn(entry);
111 Mockito.when(pool.lease(route, null, null)).thenReturn(future);
112
113 final ConnectionRequest connRequest1 = mgr.requestConnection(route, null);
114 final HttpClientConnection conn1 = connRequest1.get(1, TimeUnit.SECONDS);
115 Assert.assertNotNull(conn1);
116 Assert.assertNotSame(conn, conn1);
117
118 mgr.releaseConnection(conn1, null, 0, TimeUnit.MILLISECONDS);
119
120 Mockito.verify(pool).release(entry, true);
121 }
122
123 @Test
124 public void testReleaseRouteIncomplete() throws Exception {
125 final HttpHost target = new HttpHost("localhost", 80);
126 final HttpRoute route = new HttpRoute(target);
127
128 final CPoolEntry entry = new CPoolEntry(LogFactory.getLog(getClass()), "id", route, conn,
129 -1, TimeUnit.MILLISECONDS);
130
131 Mockito.when(future.isCancelled()).thenReturn(Boolean.FALSE);
132 Mockito.when(socketFactoryRegistry.lookup("http")).thenReturn(plainSocketFactory);
133 Mockito.when(schemePortResolver.resolve(target)).thenReturn(80);
134 Mockito.when(plainSocketFactory.createSocket(Mockito.<HttpContext>any())).thenReturn(socket);
135
136 Mockito.when(conn.isOpen()).thenReturn(true);
137 Mockito.when(future.isCancelled()).thenReturn(false);
138 Mockito.when(future.get(1, TimeUnit.SECONDS)).thenReturn(entry);
139 Mockito.when(pool.lease(route, null, null)).thenReturn(future);
140
141 final ConnectionRequest connRequest1 = mgr.requestConnection(route, null);
142 final HttpClientConnection conn1 = connRequest1.get(1, TimeUnit.SECONDS);
143 Assert.assertNotNull(conn1);
144 Assert.assertNotSame(conn, conn1);
145
146 mgr.releaseConnection(conn1, null, 0, TimeUnit.MILLISECONDS);
147
148 Mockito.verify(pool).release(entry, false);
149 }
150
151 @Test(expected= ExecutionException.class)
152 public void testLeaseFutureCancelled() throws Exception {
153 final HttpHost target = new HttpHost("localhost", 80);
154 final HttpRoute route = new HttpRoute(target);
155
156 final CPoolEntry entry = new CPoolEntry(LogFactory.getLog(getClass()), "id", route, conn,
157 -1, TimeUnit.MILLISECONDS);
158 entry.markRouteComplete();
159
160 Mockito.when(future.isCancelled()).thenReturn(Boolean.TRUE);
161 Mockito.when(future.get(1, TimeUnit.SECONDS)).thenReturn(entry);
162 Mockito.when(pool.lease(route, null, null)).thenReturn(future);
163
164 final ConnectionRequest connRequest1 = mgr.requestConnection(route, null);
165 connRequest1.get(1, TimeUnit.SECONDS);
166 }
167
168 @Test(expected=ConnectionPoolTimeoutException.class)
169 public void testLeaseFutureTimeout() throws Exception {
170 final HttpHost target = new HttpHost("localhost", 80);
171 final HttpRoute route = new HttpRoute(target);
172
173 Mockito.when(future.isCancelled()).thenReturn(Boolean.TRUE);
174 Mockito.when(future.get(1, TimeUnit.SECONDS)).thenThrow(new TimeoutException());
175 Mockito.when(pool.lease(route, null, null)).thenReturn(future);
176
177 final ConnectionRequest connRequest1 = mgr.requestConnection(route, null);
178 connRequest1.get(1, TimeUnit.SECONDS);
179 }
180
181 @Test
182 public void testReleaseReusable() throws Exception {
183 final HttpHost target = new HttpHost("localhost", 80);
184 final HttpRoute route = new HttpRoute(target);
185
186 final CPoolEntry entry = Mockito.spy(new CPoolEntry(LogFactory.getLog(getClass()), "id", route, conn,
187 -1, TimeUnit.MILLISECONDS));
188 entry.markRouteComplete();
189
190 Mockito.when(future.isCancelled()).thenReturn(Boolean.FALSE);
191 Mockito.when(future.get(1, TimeUnit.SECONDS)).thenReturn(entry);
192 Mockito.when(pool.lease(route, null, null)).thenReturn(future);
193 Mockito.when(conn.isOpen()).thenReturn(Boolean.TRUE);
194
195 final ConnectionRequest connRequest1 = mgr.requestConnection(route, null);
196 final HttpClientConnection conn1 = connRequest1.get(1, TimeUnit.SECONDS);
197 Assert.assertNotNull(conn1);
198 Assert.assertTrue(conn1.isOpen());
199
200 mgr.releaseConnection(conn1, "some state", 0, TimeUnit.MILLISECONDS);
201
202 Mockito.verify(pool).release(entry, true);
203 Mockito.verify(entry).setState("some state");
204 Mockito.verify(entry).updateExpiry(Mockito.anyLong(), Mockito.eq(TimeUnit.MILLISECONDS));
205 }
206
207 @Test
208 public void testReleaseNonReusable() throws Exception {
209 final HttpHost target = new HttpHost("localhost", 80);
210 final HttpRoute route = new HttpRoute(target);
211
212 final CPoolEntry entry = Mockito.spy(new CPoolEntry(LogFactory.getLog(getClass()), "id", route, conn,
213 -1, TimeUnit.MILLISECONDS));
214 entry.markRouteComplete();
215
216 Mockito.when(future.isCancelled()).thenReturn(Boolean.FALSE);
217 Mockito.when(future.get(1, TimeUnit.SECONDS)).thenReturn(entry);
218 Mockito.when(pool.lease(route, null, null)).thenReturn(future);
219 Mockito.when(conn.isOpen()).thenReturn(Boolean.FALSE);
220
221 final ConnectionRequest connRequest1 = mgr.requestConnection(route, null);
222 final HttpClientConnection conn1 = connRequest1.get(1, TimeUnit.SECONDS);
223 Assert.assertNotNull(conn1);
224 Assert.assertFalse(conn1.isOpen());
225
226 mgr.releaseConnection(conn1, "some state", 0, TimeUnit.MILLISECONDS);
227
228 Mockito.verify(pool).release(entry, false);
229 Mockito.verify(entry, Mockito.never()).setState(Mockito.anyObject());
230 Mockito.verify(entry, Mockito.never()).updateExpiry(Mockito.anyLong(), Mockito.eq(TimeUnit.MILLISECONDS));
231 }
232
233 @Test
234 public void testTargetConnect() throws Exception {
235 final HttpHost target = new HttpHost("somehost", 443, "https");
236 final InetAddress remote = InetAddress.getByAddress(new byte[] {10, 0, 0, 1});
237 final InetAddress local = InetAddress.getByAddress(new byte[]{127, 0, 0, 1});
238 final HttpRoute route = new HttpRoute(target, local, true);
239
240 final CPoolEntry entry = new CPoolEntry(LogFactory.getLog(getClass()), "id", route, conn,
241 -1, TimeUnit.MILLISECONDS);
242 entry.markRouteComplete();
243 Mockito.when(future.isCancelled()).thenReturn(Boolean.FALSE);
244 Mockito.when(conn.isOpen()).thenReturn(true);
245 Mockito.when(future.isCancelled()).thenReturn(false);
246 Mockito.when(future.get(1, TimeUnit.SECONDS)).thenReturn(entry);
247 Mockito.when(pool.lease(route, null, null)).thenReturn(future);
248
249 final ConnectionRequest connRequest1 = mgr.requestConnection(route, null);
250 final HttpClientConnection conn1 = connRequest1.get(1, TimeUnit.SECONDS);
251 Assert.assertNotNull(conn1);
252
253 final HttpClientContext context = HttpClientContext.create();
254 final SocketConfig sconfig = SocketConfig.custom().build();
255
256 mgr.setDefaultSocketConfig(sconfig);
257
258 Mockito.when(dnsResolver.resolve("somehost")).thenReturn(new InetAddress[]{remote});
259 Mockito.when(schemePortResolver.resolve(target)).thenReturn(8443);
260 Mockito.when(socketFactoryRegistry.lookup("https")).thenReturn(plainSocketFactory);
261 Mockito.when(plainSocketFactory.createSocket(Mockito.<HttpContext>any())).thenReturn(socket);
262 Mockito.when(plainSocketFactory.connectSocket(
263 Mockito.anyInt(),
264 Mockito.eq(socket),
265 Mockito.<HttpHost>any(),
266 Mockito.<InetSocketAddress>any(),
267 Mockito.<InetSocketAddress>any(),
268 Mockito.<HttpContext>any())).thenReturn(socket);
269
270 mgr.connect(conn1, route, 123, context);
271
272 Mockito.verify(dnsResolver, Mockito.times(1)).resolve("somehost");
273 Mockito.verify(schemePortResolver, Mockito.times(1)).resolve(target);
274 Mockito.verify(plainSocketFactory, Mockito.times(1)).createSocket(context);
275 Mockito.verify(plainSocketFactory, Mockito.times(1)).connectSocket(123, socket, target,
276 new InetSocketAddress(remote, 8443),
277 new InetSocketAddress(local, 0), context);
278
279 mgr.routeComplete(conn1, route, context);
280 }
281
282 @Test
283 public void testProxyConnectAndUpgrade() throws Exception {
284 final HttpHost target = new HttpHost("somehost", 443, "https");
285 final HttpHost proxy = new HttpHost("someproxy", 8080);
286 final InetAddress remote = InetAddress.getByAddress(new byte[] {10, 0, 0, 1});
287 final InetAddress local = InetAddress.getByAddress(new byte[] {127, 0, 0, 1});
288 final HttpRoute route = new HttpRoute(target, local, proxy, true);
289
290 final CPoolEntry entry = new CPoolEntry(LogFactory.getLog(getClass()), "id", route, conn,
291 -1, TimeUnit.MILLISECONDS);
292 entry.markRouteComplete();
293 Mockito.when(future.isCancelled()).thenReturn(Boolean.FALSE);
294 Mockito.when(conn.isOpen()).thenReturn(true);
295 Mockito.when(future.isCancelled()).thenReturn(false);
296 Mockito.when(future.get(1, TimeUnit.SECONDS)).thenReturn(entry);
297 Mockito.when(pool.lease(route, null, null)).thenReturn(future);
298
299 final ConnectionRequest connRequest1 = mgr.requestConnection(route, null);
300 final HttpClientConnection conn1 = connRequest1.get(1, TimeUnit.SECONDS);
301 Assert.assertNotNull(conn1);
302
303 final ConnectionSocketFactory plainsf = Mockito.mock(ConnectionSocketFactory.class);
304 final LayeredConnectionSocketFactory sslsf = Mockito.mock(LayeredConnectionSocketFactory.class);
305 final Socket mockSock = Mockito.mock(Socket.class);
306 final HttpClientContext context = HttpClientContext.create();
307 final SocketConfig sconfig = SocketConfig.custom().build();
308 final ConnectionConfig cconfig = ConnectionConfig.custom().build();
309
310 mgr.setDefaultSocketConfig(sconfig);
311 mgr.setDefaultConnectionConfig(cconfig);
312
313 Mockito.when(dnsResolver.resolve("someproxy")).thenReturn(new InetAddress[] {remote});
314 Mockito.when(schemePortResolver.resolve(proxy)).thenReturn(8080);
315 Mockito.when(schemePortResolver.resolve(target)).thenReturn(8443);
316 Mockito.when(socketFactoryRegistry.lookup("http")).thenReturn(plainsf);
317 Mockito.when(socketFactoryRegistry.lookup("https")).thenReturn(sslsf);
318 Mockito.when(plainsf.createSocket(Mockito.<HttpContext>any())).thenReturn(mockSock);
319 Mockito.when(plainsf.connectSocket(
320 Mockito.anyInt(),
321 Mockito.eq(mockSock),
322 Mockito.<HttpHost>any(),
323 Mockito.<InetSocketAddress>any(),
324 Mockito.<InetSocketAddress>any(),
325 Mockito.<HttpContext>any())).thenReturn(mockSock);
326
327 mgr.connect(conn1, route, 123, context);
328
329 Mockito.verify(dnsResolver, Mockito.times(1)).resolve("someproxy");
330 Mockito.verify(schemePortResolver, Mockito.times(1)).resolve(proxy);
331 Mockito.verify(plainsf, Mockito.times(1)).createSocket(context);
332 Mockito.verify(plainsf, Mockito.times(1)).connectSocket(123, mockSock, proxy,
333 new InetSocketAddress(remote, 8080),
334 new InetSocketAddress(local, 0), context);
335
336 Mockito.when(conn.getSocket()).thenReturn(mockSock);
337
338 mgr.upgrade(conn1, route, context);
339
340 Mockito.verify(schemePortResolver, Mockito.times(1)).resolve(target);
341 Mockito.verify(sslsf, Mockito.times(1)).createLayeredSocket(
342 mockSock, "somehost", 8443, context);
343
344 mgr.routeComplete(conn1, route, context);
345 }
346
347 }