/* * Copyright 2010-2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"). * You may not use this file except in compliance with the License. * A copy of the License is located at * * http://aws.amazon.com/apache2.0 * * or in the "license" file accompanying this file. This file 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. */ package com.amazonaws; import com.amazonaws.retry.PredefinedRetryPolicies; import com.amazonaws.retry.RetryPolicy; import com.amazonaws.util.ImmutableMapParameter; import java.util.ArrayList; import java.util.List; import org.apache.commons.lang.RandomStringUtils; import org.apache.http.conn.socket.ConnectionSocketFactory; import org.apache.http.conn.ssl.SSLSocketFactory; import org.junit.Test; import org.mockito.Mockito; import java.lang.reflect.Field; import java.lang.reflect.Modifier; import java.net.InetAddress; import java.net.UnknownHostException; import java.security.KeyStore; import java.security.SecureRandom; import java.util.Random; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertSame; import static org.junit.Assert.fail; import static org.unitils.reflectionassert.ReflectionAssert.assertReflectionEquals; public class ClientConfigurationTest { private static final Random RANDOM = new Random(); private static final ClientConfiguration DEFAULT_CLIENT_CONFIG = new ClientConfiguration(); private static final RetryPolicy CUSTOM_RETRY_POLICY = new RetryPolicy( PredefinedRetryPolicies.SDKDefaultRetryCondition.NO_RETRY_CONDITION, RetryPolicy.BackoffStrategy.NO_DELAY, 1000, false); @Test public void httpClientConfiguration() throws Exception { ClientConfiguration config = new ClientConfiguration(); ApacheHttpClientConfig httpclientConfig = config.getApacheHttpClientConfig(); assertNotNull("httpclient config must never be null", httpclientConfig); assertNull("default ssl socket factory is null", httpclientConfig.getSslSocketFactory()); SSLSocketFactory customFactory = new SSLSocketFactory((KeyStore) null); config.getApacheHttpClientConfig().setSslSocketFactory(customFactory); assertSame("custom ssl socket factory configured", customFactory, config.getApacheHttpClientConfig().getSslSocketFactory()); config.getApacheHttpClientConfig().setSslSocketFactory(null); assertNull("no more custom ssl socket factory configured", config .getApacheHttpClientConfig().getSslSocketFactory()); config.getApacheHttpClientConfig().withSslSocketFactory(customFactory); assertSame("custom ssl socket factory configured via fluent API", customFactory, config.getApacheHttpClientConfig().getSslSocketFactory()); ClientConfiguration config2 = new ClientConfiguration(config); assertSame("custom ssl socket factory copied via ctor", customFactory, config2.getApacheHttpClientConfig().getSslSocketFactory()); config.getApacheHttpClientConfig().setSslSocketFactory(null); assertNull( "ssl socket factory set to null for the original httpclient config", config.getApacheHttpClientConfig().getSslSocketFactory()); assertNotNull( "ssl soscket of the new httpclient config should not be affected", config2.getApacheHttpClientConfig().getSslSocketFactory()); assertNotNull("Client Configuration must have a default DnsResolver", config.getDnsResolver()); try { config.setDnsResolver(null); fail("Expected IllegalArgumentException"); } catch (IllegalArgumentException expected) { } DnsResolver resolver = new DnsResolver() { @Override public InetAddress[] resolve(String s) throws UnknownHostException { return new InetAddress[0]; } }; config.setDnsResolver(resolver); assertSame("custom dns resolver set via fluent API", resolver, config.getDnsResolver()); } private void clearProxyProperties() { System.clearProperty("http.proxyHost"); System.clearProperty("http.proxyPort"); System.clearProperty("https.proxyHost"); System.clearProperty("https.proxyPort"); System.clearProperty("http.nonProxyHosts"); } @Test public void testNonProxyHostsSetting() throws Exception { clearProxyProperties(); // test ClientConfiguration setting ClientConfiguration config; config = new ClientConfiguration().withNonProxyHosts("foo.com"); assertEquals("foo.com", config.getNonProxyHosts()); config.setProtocol(Protocol.HTTP); assertEquals("foo.com", config.getNonProxyHosts()); // test system property System.setProperty("http.nonProxyHosts", "foo.com"); config = new ClientConfiguration(); assertEquals("foo.com", config.getNonProxyHosts()); config.setProtocol(Protocol.HTTP); assertEquals("foo.com", config.getNonProxyHosts()); System.clearProperty("http.nonProxyHosts"); // ClientConfiguration setting has a precedence over system property System.setProperty("http.nonProxyHosts", "bar.com"); config = new ClientConfiguration().withNonProxyHosts("foo.com"); assertEquals("foo.com", config.getNonProxyHosts()); config.setProtocol(Protocol.HTTP); assertEquals("foo.com", config.getNonProxyHosts()); System.clearProperty("http.nonProxyHosts"); // ClientConfiguration setting has a precedence over system property config = new ClientConfiguration(); assertNull(config.getNonProxyHosts()); config.setProtocol(Protocol.HTTP); assertNull(config.getNonProxyHosts()); } @Test public void testProxySystemProperties() throws Exception { clearProxyProperties(); ClientConfiguration config; config = new ClientConfiguration(); assertNull(config.getProxyHost()); assertEquals(config.getProxyPort(), -1); assertNull(config.getProxyUsername()); assertNull(config.getProxyPassword()); config.setProtocol(Protocol.HTTP); assertNull(config.getProxyHost()); assertEquals(config.getProxyPort(), -1); assertNull(config.getProxyUsername()); assertNull(config.getProxyPassword()); System.setProperty("https.proxyHost", "foo"); config = new ClientConfiguration(); assertEquals(config.getProxyHost(), "foo"); config.setProtocol(Protocol.HTTP); assertNull(config.getProxyHost()); System.clearProperty("https.proxyHost"); System.setProperty("http.proxyHost", "foo"); config = new ClientConfiguration(); assertNull(config.getProxyHost()); config.setProtocol(Protocol.HTTP); assertEquals(config.getProxyHost(), "foo"); System.clearProperty("http.proxyHost"); System.setProperty("https.proxyPort", "8443"); config = new ClientConfiguration(); assertEquals(config.getProxyPort(), 8443); config.setProtocol(Protocol.HTTP); assertEquals(config.getProxyPort(), -1); System.clearProperty("https.proxyPort"); System.setProperty("http.proxyPort", "8080"); config = new ClientConfiguration(); assertEquals(config.getProxyPort(), -1); config.setProtocol(Protocol.HTTP); assertEquals(config.getProxyPort(), 8080); System.clearProperty("http.proxyPort"); System.setProperty("https.proxyUser", "foo"); config = new ClientConfiguration(); assertEquals(config.getProxyUsername(), "foo"); config.setProtocol(Protocol.HTTP); assertNull(config.getProxyUsername()); System.clearProperty("https.proxyUser"); System.setProperty("http.proxyUser", "foo"); config = new ClientConfiguration(); assertNull(config.getProxyUsername()); config.setProtocol(Protocol.HTTP); assertEquals(config.getProxyUsername(), "foo"); System.clearProperty("http.proxyUser"); System.setProperty("https.proxyPassword", "foo"); config = new ClientConfiguration(); assertEquals(config.getProxyPassword(), "foo"); config.setProtocol(Protocol.HTTP); assertNull(config.getProxyPassword()); System.clearProperty("https.proxyPassword"); System.setProperty("http.proxyPassword", "foo"); config = new ClientConfiguration(); assertNull(config.getProxyPassword()); config.setProtocol(Protocol.HTTP); assertEquals(config.getProxyPassword(), "foo"); System.clearProperty("http.proxyPassword"); } @Test public void testHeadersDeepCopyInConstructor() { String key1 = "key1", value1 = "value1"; String key2 = "key2", value2 = "value2"; ClientConfiguration source = new ClientConfiguration().withHeader(key1, value1).withHeader(key2, value2); ClientConfiguration target = new ClientConfiguration(source); assertEquals(2, target.getHeaders().size()); assertEquals(value1, target.getHeaders().get(key1)); assertEquals(value2, target.getHeaders().get(key2)); source.withHeader(key1, "value3"); source.withHeader("new key", "new value"); assertEquals(2, target.getHeaders().size()); assertEquals(value1, target.getHeaders().get(key1)); assertEquals(value2, target.getHeaders().get(key2)); } @Test public void clientConfigurationCopyConstructor_CopiesAllValues() throws Exception { ClientConfiguration customConfig = new ClientConfiguration(); for (Field field : ClientConfiguration.class.getDeclaredFields()) { if (isStaticField(field)) { continue; } field.setAccessible(true); final Class<?> clzz = field.getType(); if (clzz.isAssignableFrom(int.class) || clzz.isAssignableFrom(long.class)) { field.set(customConfig, Math.abs(RANDOM.nextInt())); } else if (clzz.isAssignableFrom(boolean.class)) { // Invert the default value to ensure it's different field.set(customConfig, !(Boolean) field.get(customConfig)); } else if (clzz.isAssignableFrom(String.class)) { field.set(customConfig, RandomStringUtils.random(10)); } else if (clzz.isAssignableFrom(RetryPolicy.class)) { field.set(customConfig, CUSTOM_RETRY_POLICY); } else if (clzz.isAssignableFrom(InetAddress.class)) { field.set(customConfig, InetAddress.getLocalHost()); } else if (clzz.isAssignableFrom(Protocol.class)) { // Default is HTTPS so switch to HTTP field.set(customConfig, Protocol.HTTP); } else if (clzz.isAssignableFrom(DnsResolver.class)) { field.set(customConfig, new MyCustomDnsResolver()); } else if (clzz.isAssignableFrom(SecureRandom.class)) { field.set(customConfig, new SecureRandom()); } else if (field.getName().equals("headers")) { field.set(customConfig, ImmutableMapParameter.of("foo", "bar")); } else if (clzz.isAssignableFrom(ApacheHttpClientConfig.class)) { customConfig.getApacheHttpClientConfig() .setSslSocketFactory(Mockito.mock(ConnectionSocketFactory.class)); } else if (clzz.isAssignableFrom(List.class)) { field.set(customConfig, new ArrayList<Object>()); } else { throw new RuntimeException( String.format("Field %s of type %s is not supported", field.getName(), field.getType())); } // Extra check to make sure the value differs from the default and we haven't missed something assertNotEquals( String.format("Field %s does not differ from default value", field.getName()), field.get(DEFAULT_CLIENT_CONFIG), field.get(customConfig)); } // Do a deep comparison of the config after sending it through the copy constructor assertReflectionEquals(customConfig, new ClientConfiguration(customConfig)); } private boolean isStaticField(Field field) { return (field.getModifiers() & Modifier.STATIC) == Modifier.STATIC; } public static class MyCustomDnsResolver implements DnsResolver { @Override public InetAddress[] resolve(String host) throws UnknownHostException { return new InetAddress[0]; } } }