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