| /* |
| * ==================================================================== |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| * ==================================================================== |
| * |
| * This software consists of voluntary contributions made by many |
| * individuals on behalf of the Apache Software Foundation. For more |
| * information on the Apache Software Foundation, please see |
| * <http://www.apache.org/>. |
| * |
| */ |
| |
| package org.apache.http.impl.conn; |
| |
| import java.net.ConnectException; |
| import java.net.SocketException; |
| import java.net.InetAddress; |
| import java.net.InetSocketAddress; |
| import java.net.Socket; |
| import java.net.SocketTimeoutException; |
| |
| import org.apache.http.HttpHost; |
| import org.apache.http.config.Lookup; |
| import org.apache.http.config.SocketConfig; |
| import org.apache.http.conn.ConnectTimeoutException; |
| import org.apache.http.conn.DnsResolver; |
| import org.apache.http.conn.HttpHostConnectException; |
| import org.apache.http.conn.SchemePortResolver; |
| import org.apache.http.conn.ManagedHttpClientConnection; |
| import org.apache.http.conn.UnsupportedSchemeException; |
| import org.apache.http.conn.socket.ConnectionSocketFactory; |
| import org.apache.http.conn.socket.LayeredConnectionSocketFactory; |
| import org.apache.http.protocol.BasicHttpContext; |
| import org.apache.http.protocol.HttpContext; |
| import org.junit.Before; |
| import org.junit.Test; |
| import org.mockito.Mockito; |
| |
| @SuppressWarnings({"boxing","static-access"}) // test code |
| public class TestHttpClientConnectionOperator { |
| |
| private ManagedHttpClientConnection conn; |
| private Socket socket; |
| private ConnectionSocketFactory plainSocketFactory; |
| private LayeredConnectionSocketFactory sslSocketFactory; |
| private Lookup<ConnectionSocketFactory> socketFactoryRegistry; |
| private SchemePortResolver schemePortResolver; |
| private DnsResolver dnsResolver; |
| private DefaultHttpClientConnectionOperator connectionOperator; |
| |
| @SuppressWarnings("unchecked") |
| @Before |
| public void setup() throws Exception { |
| conn = Mockito.mock(ManagedHttpClientConnection.class); |
| socket = Mockito.mock(Socket.class); |
| plainSocketFactory = Mockito.mock(ConnectionSocketFactory.class); |
| sslSocketFactory = Mockito.mock(LayeredConnectionSocketFactory.class); |
| socketFactoryRegistry = Mockito.mock(Lookup.class); |
| schemePortResolver = Mockito.mock(SchemePortResolver.class); |
| dnsResolver = Mockito.mock(DnsResolver.class); |
| connectionOperator = new DefaultHttpClientConnectionOperator( |
| socketFactoryRegistry, schemePortResolver, dnsResolver); |
| } |
| |
| @Test |
| public void testConnect() throws Exception { |
| final HttpContext context = new BasicHttpContext(); |
| final HttpHost host = new HttpHost("somehost"); |
| final InetAddress local = InetAddress.getByAddress(new byte[] {127, 0, 0, 0}); |
| final InetAddress ip1 = InetAddress.getByAddress(new byte[] {127, 0, 0, 1}); |
| final InetAddress ip2 = InetAddress.getByAddress(new byte[] {127, 0, 0, 2}); |
| |
| Mockito.when(dnsResolver.resolve("somehost")).thenReturn(new InetAddress[] { ip1, ip2 }); |
| Mockito.when(socketFactoryRegistry.lookup("http")).thenReturn(plainSocketFactory); |
| Mockito.when(schemePortResolver.resolve(host)).thenReturn(80); |
| Mockito.when(plainSocketFactory.createSocket(Mockito.<HttpContext>any())).thenReturn(socket); |
| Mockito.when(plainSocketFactory.connectSocket( |
| Mockito.anyInt(), |
| Mockito.<Socket>any(), |
| Mockito.<HttpHost>any(), |
| Mockito.<InetSocketAddress>any(), |
| Mockito.<InetSocketAddress>any(), |
| Mockito.<HttpContext>any())).thenReturn(socket); |
| |
| final SocketConfig socketConfig = SocketConfig.custom() |
| .setSoKeepAlive(true) |
| .setSoReuseAddress(true) |
| .setSoTimeout(5000) |
| .setTcpNoDelay(true) |
| .setSoLinger(50) |
| .build(); |
| final InetSocketAddress localAddress = new InetSocketAddress(local, 0); |
| connectionOperator.connect(conn, host, localAddress, 1000, socketConfig, context); |
| |
| Mockito.verify(socket).setKeepAlive(true); |
| Mockito.verify(socket).setReuseAddress(true); |
| Mockito.verify(socket).setSoTimeout(5000); |
| Mockito.verify(socket).setSoLinger(true, 50); |
| Mockito.verify(socket).setTcpNoDelay(true); |
| |
| Mockito.verify(plainSocketFactory).connectSocket( |
| 1000, |
| socket, |
| host, |
| new InetSocketAddress(ip1, 80), |
| localAddress, |
| context); |
| Mockito.verify(conn, Mockito.times(2)).bind(socket); |
| } |
| |
| @Test(expected=ConnectTimeoutException.class) |
| public void testConnectTimeout() throws Exception { |
| final HttpContext context = new BasicHttpContext(); |
| final HttpHost host = new HttpHost("somehost"); |
| final InetAddress ip1 = InetAddress.getByAddress(new byte[] {10, 0, 0, 1}); |
| final InetAddress ip2 = InetAddress.getByAddress(new byte[] {10, 0, 0, 2}); |
| |
| Mockito.when(dnsResolver.resolve("somehost")).thenReturn(new InetAddress[] { ip1, ip2 }); |
| Mockito.when(socketFactoryRegistry.lookup("http")).thenReturn(plainSocketFactory); |
| Mockito.when(schemePortResolver.resolve(host)).thenReturn(80); |
| Mockito.when(plainSocketFactory.createSocket(Mockito.<HttpContext>any())).thenReturn(socket); |
| Mockito.when(plainSocketFactory.connectSocket( |
| Mockito.anyInt(), |
| Mockito.<Socket>any(), |
| Mockito.<HttpHost>any(), |
| Mockito.<InetSocketAddress>any(), |
| Mockito.<InetSocketAddress>any(), |
| Mockito.<HttpContext>any())).thenThrow(new SocketTimeoutException()); |
| |
| connectionOperator.connect(conn, host, null, 1000, SocketConfig.DEFAULT, context); |
| } |
| |
| @Test(expected=HttpHostConnectException.class) |
| public void testConnectFailure() throws Exception { |
| final HttpContext context = new BasicHttpContext(); |
| final HttpHost host = new HttpHost("somehost"); |
| final InetAddress ip1 = InetAddress.getByAddress(new byte[] {10, 0, 0, 1}); |
| final InetAddress ip2 = InetAddress.getByAddress(new byte[] {10, 0, 0, 2}); |
| |
| Mockito.when(dnsResolver.resolve("somehost")).thenReturn(new InetAddress[] { ip1, ip2 }); |
| Mockito.when(socketFactoryRegistry.lookup("http")).thenReturn(plainSocketFactory); |
| Mockito.when(schemePortResolver.resolve(host)).thenReturn(80); |
| Mockito.when(plainSocketFactory.createSocket(Mockito.<HttpContext>any())).thenReturn(socket); |
| Mockito.when(plainSocketFactory.connectSocket( |
| Mockito.anyInt(), |
| Mockito.<Socket>any(), |
| Mockito.<HttpHost>any(), |
| Mockito.<InetSocketAddress>any(), |
| Mockito.<InetSocketAddress>any(), |
| Mockito.<HttpContext>any())).thenThrow(new ConnectException()); |
| |
| connectionOperator.connect(conn, host, null, 1000, SocketConfig.DEFAULT, context); |
| } |
| |
| @Test |
| public void testConnectFailover() throws Exception { |
| final HttpContext context = new BasicHttpContext(); |
| final HttpHost host = new HttpHost("somehost"); |
| final InetAddress local = InetAddress.getByAddress(new byte[] {127, 0, 0, 0}); |
| final InetAddress ip1 = InetAddress.getByAddress(new byte[] {10, 0, 0, 1}); |
| final InetAddress ip2 = InetAddress.getByAddress(new byte[] {10, 0, 0, 2}); |
| |
| Mockito.when(dnsResolver.resolve("somehost")).thenReturn(new InetAddress[] { ip1, ip2 }); |
| Mockito.when(socketFactoryRegistry.lookup("http")).thenReturn(plainSocketFactory); |
| Mockito.when(schemePortResolver.resolve(host)).thenReturn(80); |
| Mockito.when(plainSocketFactory.createSocket(Mockito.<HttpContext>any())).thenReturn(socket); |
| Mockito.when(plainSocketFactory.connectSocket( |
| Mockito.anyInt(), |
| Mockito.<Socket>any(), |
| Mockito.<HttpHost>any(), |
| Mockito.eq(new InetSocketAddress(ip1, 80)), |
| Mockito.<InetSocketAddress>any(), |
| Mockito.<HttpContext>any())).thenThrow(new ConnectException()); |
| Mockito.when(plainSocketFactory.connectSocket( |
| Mockito.anyInt(), |
| Mockito.<Socket>any(), |
| Mockito.<HttpHost>any(), |
| Mockito.eq(new InetSocketAddress(ip2, 80)), |
| Mockito.<InetSocketAddress>any(), |
| Mockito.<HttpContext>any())).thenReturn(socket); |
| |
| final InetSocketAddress localAddress = new InetSocketAddress(local, 0); |
| connectionOperator.connect(conn, host, localAddress, 1000, SocketConfig.DEFAULT, context); |
| |
| Mockito.verify(plainSocketFactory).connectSocket( |
| 1000, |
| socket, |
| host, |
| new InetSocketAddress(ip2, 80), |
| localAddress, |
| context); |
| Mockito.verify(conn, Mockito.times(3)).bind(socket); |
| } |
| |
| @Test |
| public void testConnectFailoverSocketException() throws Exception { |
| final HttpContext context = new BasicHttpContext(); |
| final HttpHost host = new HttpHost("somehost"); |
| final InetAddress local = InetAddress.getByAddress(new byte[] {127, 0, 0, 0}); |
| final InetAddress ip1 = InetAddress.getByAddress(new byte[] {10, 0, 0, 1}); |
| final InetAddress ip2 = InetAddress.getByAddress(new byte[] {10, 0, 0, 2}); |
| |
| Mockito.when(dnsResolver.resolve("somehost")).thenReturn(new InetAddress[] { ip1, ip2 }); |
| Mockito.when(socketFactoryRegistry.lookup("http")).thenReturn(plainSocketFactory); |
| Mockito.when(schemePortResolver.resolve(host)).thenReturn(80); |
| Mockito.when(plainSocketFactory.createSocket(Mockito.<HttpContext>any())).thenReturn(socket); |
| Mockito.when(plainSocketFactory.connectSocket( |
| Mockito.anyInt(), |
| Mockito.<Socket>any(), |
| Mockito.<HttpHost>any(), |
| Mockito.eq(new InetSocketAddress(ip1, 80)), |
| Mockito.<InetSocketAddress>any(), |
| Mockito.<HttpContext>any())).thenThrow(new SocketException()); |
| Mockito.when(plainSocketFactory.connectSocket( |
| Mockito.anyInt(), |
| Mockito.<Socket>any(), |
| Mockito.<HttpHost>any(), |
| Mockito.eq(new InetSocketAddress(ip2, 80)), |
| Mockito.<InetSocketAddress>any(), |
| Mockito.<HttpContext>any())).thenReturn(socket); |
| |
| final InetSocketAddress localAddress = new InetSocketAddress(local, 0); |
| connectionOperator.connect(conn, host, localAddress, 1000, SocketConfig.DEFAULT, context); |
| |
| Mockito.verify(plainSocketFactory).connectSocket( |
| 1000, |
| socket, |
| host, |
| new InetSocketAddress(ip2, 80), |
| localAddress, |
| context); |
| Mockito.verify(conn, Mockito.times(3)).bind(socket); |
| } |
| |
| @Test |
| public void testConnectExplicitAddress() throws Exception { |
| final HttpContext context = new BasicHttpContext(); |
| final InetAddress local = InetAddress.getByAddress(new byte[] {127, 0, 0, 0}); |
| final InetAddress ip = InetAddress.getByAddress(new byte[] {127, 0, 0, 23}); |
| final HttpHost host = new HttpHost(ip); |
| |
| Mockito.when(socketFactoryRegistry.lookup("http")).thenReturn(plainSocketFactory); |
| Mockito.when(schemePortResolver.resolve(host)).thenReturn(80); |
| Mockito.when(plainSocketFactory.createSocket(Mockito.<HttpContext>any())).thenReturn(socket); |
| Mockito.when(plainSocketFactory.connectSocket( |
| Mockito.anyInt(), |
| Mockito.<Socket>any(), |
| Mockito.<HttpHost>any(), |
| Mockito.<InetSocketAddress>any(), |
| Mockito.<InetSocketAddress>any(), |
| Mockito.<HttpContext>any())).thenReturn(socket); |
| |
| final InetSocketAddress localAddress = new InetSocketAddress(local, 0); |
| connectionOperator.connect(conn, host, localAddress, 1000, SocketConfig.DEFAULT, context); |
| |
| Mockito.verify(plainSocketFactory).connectSocket( |
| 1000, |
| socket, |
| host, |
| new InetSocketAddress(ip, 80), |
| localAddress, |
| context); |
| Mockito.verify(dnsResolver, Mockito.never()).resolve(Mockito.anyString()); |
| Mockito.verify(conn, Mockito.times(2)).bind(socket); |
| } |
| |
| @Test |
| public void testUpgrade() throws Exception { |
| final HttpContext context = new BasicHttpContext(); |
| final HttpHost host = new HttpHost("somehost", -1, "https"); |
| |
| Mockito.when(socketFactoryRegistry.lookup("https")).thenReturn(sslSocketFactory); |
| Mockito.when(schemePortResolver.resolve(host)).thenReturn(443); |
| Mockito.when(sslSocketFactory.createSocket(Mockito.<HttpContext>any())).thenReturn(socket); |
| Mockito.when(sslSocketFactory.createLayeredSocket( |
| Mockito.<Socket>any(), |
| Mockito.eq("somehost"), |
| Mockito.eq(443), |
| Mockito.<HttpContext>any())).thenReturn(socket); |
| |
| connectionOperator.upgrade(conn, host, context); |
| |
| Mockito.verify(conn).bind(socket); |
| } |
| |
| @Test(expected=UnsupportedSchemeException.class) |
| public void testUpgradeUpsupportedScheme() throws Exception { |
| final HttpContext context = new BasicHttpContext(); |
| final HttpHost host = new HttpHost("somehost", -1, "httpsssss"); |
| Mockito.when(socketFactoryRegistry.lookup("http")).thenReturn(plainSocketFactory); |
| |
| connectionOperator.upgrade(conn, host, context); |
| } |
| |
| @Test(expected=UnsupportedSchemeException.class) |
| public void testUpgradeNonLayeringScheme() throws Exception { |
| final HttpContext context = new BasicHttpContext(); |
| final HttpHost host = new HttpHost("somehost", -1, "http"); |
| Mockito.when(socketFactoryRegistry.lookup("http")).thenReturn(plainSocketFactory); |
| |
| connectionOperator.upgrade(conn, host, context); |
| } |
| |
| } |