blob: 63165bf48e5b6213f638a1c9cadb836a55aa3319 [file] [log] [blame]
/*
* 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.
*/
package org.apache.geode.distributed.internal;
import static org.apache.geode.distributed.ConfigurationProperties.ARCHIVE_DISK_SPACE_LIMIT;
import static org.apache.geode.distributed.ConfigurationProperties.ARCHIVE_FILE_SIZE_LIMIT;
import static org.apache.geode.distributed.ConfigurationProperties.CACHE_XML_FILE;
import static org.apache.geode.distributed.ConfigurationProperties.CLUSTER_SSL_ENABLED;
import static org.apache.geode.distributed.ConfigurationProperties.GATEWAY_SSL_ENABLED;
import static org.apache.geode.distributed.ConfigurationProperties.GROUPS;
import static org.apache.geode.distributed.ConfigurationProperties.HTTP_SERVICE_SSL_ENABLED;
import static org.apache.geode.distributed.ConfigurationProperties.JMX_MANAGER_SSL_ENABLED;
import static org.apache.geode.distributed.ConfigurationProperties.LOCATORS;
import static org.apache.geode.distributed.ConfigurationProperties.LOG_DISK_SPACE_LIMIT;
import static org.apache.geode.distributed.ConfigurationProperties.LOG_FILE_SIZE_LIMIT;
import static org.apache.geode.distributed.ConfigurationProperties.LOG_LEVEL;
import static org.apache.geode.distributed.ConfigurationProperties.MCAST_PORT;
import static org.apache.geode.distributed.ConfigurationProperties.MEMBERSHIP_PORT_RANGE;
import static org.apache.geode.distributed.ConfigurationProperties.MEMBER_TIMEOUT;
import static org.apache.geode.distributed.ConfigurationProperties.NAME;
import static org.apache.geode.distributed.ConfigurationProperties.SECURITY_AUTH_TOKEN_ENABLED_COMPONENTS;
import static org.apache.geode.distributed.ConfigurationProperties.SERVER_SSL_ENABLED;
import static org.apache.geode.distributed.ConfigurationProperties.SSL_ENABLED_COMPONENTS;
import static org.apache.geode.distributed.ConfigurationProperties.START_LOCATOR;
import static org.apache.geode.distributed.ConfigurationProperties.STATISTIC_ARCHIVE_FILE;
import static org.apache.geode.distributed.ConfigurationProperties.STATISTIC_SAMPLE_RATE;
import static org.apache.geode.distributed.ConfigurationProperties.STATISTIC_SAMPLING_ENABLED;
import static org.apache.geode.internal.AvailablePortHelper.getRandomAvailableTCPPort;
import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.fail;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import java.io.File;
import java.io.FileWriter;
import java.net.Inet4Address;
import java.net.Inet6Address;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.net.UnknownHostException;
import java.util.Collection;
import java.util.Enumeration;
import java.util.Properties;
import java.util.logging.Level;
import io.micrometer.core.instrument.MeterRegistry;
import org.junit.After;
import org.junit.Assert;
import org.junit.Rule;
import org.junit.Test;
import org.junit.experimental.categories.Category;
import org.junit.rules.ExpectedException;
import org.apache.geode.distributed.DistributedSystem;
import org.apache.geode.distributed.DistributedSystemDisconnectedException;
import org.apache.geode.distributed.Locator;
import org.apache.geode.internal.Config;
import org.apache.geode.internal.ConfigSource;
import org.apache.geode.internal.logging.InternalLogWriter;
import org.apache.geode.metrics.internal.MetricsService;
import org.apache.geode.test.junit.categories.MembershipTest;
import org.apache.geode.util.internal.GeodeGlossary;
/**
* Tests the functionality of the {@link InternalDistributedSystem} class. Mostly checks
* configuration error checking.
*
* @since GemFire 2.1
*/
@Category({MembershipTest.class})
public class InternalDistributedSystemJUnitTest {
/**
* A connection to a distributed system created by this test
*/
private InternalDistributedSystem system;
private InternalDistributedSystem createSystem(Properties props,
MetricsService.Builder metricsSessionBuilder) {
this.system = new InternalDistributedSystem.Builder(props, metricsSessionBuilder)
.build();
return this.system;
}
/**
* Creates a <code>DistributedSystem</code> with the given configuration properties.
*/
private InternalDistributedSystem createSystem(Properties props) {
MetricsService.Builder metricsSessionBuilder = mock(MetricsService.Builder.class);
when(metricsSessionBuilder.build(any())).thenReturn(mock(MetricsService.class));
return createSystem(props, metricsSessionBuilder);
}
/**
* Disconnects any distributed system that was created by this test
*
* @see DistributedSystem#disconnect
*/
@After
public void tearDown() throws Exception {
if (this.system != null) {
this.system.disconnect();
}
}
//////// Test methods
@Test
public void testUnknownArgument() {
Properties props = new Properties();
props.put("UNKNOWN", "UNKNOWN");
try {
createSystem(props);
fail("Should have thrown an IllegalArgumentException");
} catch (IllegalArgumentException ex) {
// pass...
}
}
/**
* Tests that the default values of properties are what we expect
*/
@Test
public void testDefaultProperties() {
Properties props = new Properties();
// a loner is all this test needs
props.setProperty(MCAST_PORT, "0");
props.setProperty(LOCATORS, "");
DistributionConfig config = createSystem(props).getConfig();
assertEquals(DistributionConfig.DEFAULT_NAME, config.getName());
assertEquals(0, config.getMcastPort());
assertEquals(DistributionConfig.DEFAULT_MEMBERSHIP_PORT_RANGE[0],
config.getMembershipPortRange()[0]);
assertEquals(DistributionConfig.DEFAULT_MEMBERSHIP_PORT_RANGE[1],
config.getMembershipPortRange()[1]);
if (System.getProperty(GeodeGlossary.GEMFIRE_PREFIX + "mcast-address") == null) {
assertEquals(DistributionConfig.DEFAULT_MCAST_ADDRESS, config.getMcastAddress());
}
if (System.getProperty(GeodeGlossary.GEMFIRE_PREFIX + "bind-address") == null) {
assertEquals(DistributionConfig.DEFAULT_BIND_ADDRESS, config.getBindAddress());
}
assertEquals(DistributionConfig.DEFAULT_LOG_FILE, config.getLogFile());
// default log level gets overrided by the gemfire.properties created for unit tests.
// assertIndexDetailsEquals(DistributionConfig.DEFAULT_LOG_LEVEL, config.getLogLevel());
assertEquals(DistributionConfig.DEFAULT_STATISTIC_SAMPLING_ENABLED,
config.getStatisticSamplingEnabled());
assertEquals(DistributionConfig.DEFAULT_STATISTIC_SAMPLE_RATE, config.getStatisticSampleRate());
assertEquals(DistributionConfig.DEFAULT_STATISTIC_ARCHIVE_FILE,
config.getStatisticArchiveFile());
// ack-wait-threadshold is overridden on VM's command line using a
// system property. This is not a valid test. Hrm.
// assertIndexDetailsEquals(DistributionConfig.DEFAULT_ACK_WAIT_THRESHOLD,
// config.getAckWaitThreshold());
assertEquals(DistributionConfig.DEFAULT_ACK_SEVERE_ALERT_THRESHOLD,
config.getAckSevereAlertThreshold());
assertEquals(DistributionConfig.DEFAULT_CACHE_XML_FILE, config.getCacheXmlFile());
assertEquals(DistributionConfig.DEFAULT_ARCHIVE_DISK_SPACE_LIMIT,
config.getArchiveDiskSpaceLimit());
assertEquals(DistributionConfig.DEFAULT_ARCHIVE_FILE_SIZE_LIMIT,
config.getArchiveFileSizeLimit());
assertEquals(DistributionConfig.DEFAULT_LOG_DISK_SPACE_LIMIT, config.getLogDiskSpaceLimit());
assertEquals(DistributionConfig.DEFAULT_LOG_FILE_SIZE_LIMIT, config.getLogFileSizeLimit());
assertEquals(DistributionConfig.DEFAULT_ENABLE_NETWORK_PARTITION_DETECTION,
config.getEnableNetworkPartitionDetection());
}
@Test
public void testGetName() {
String name = "testGetName";
Properties props = new Properties();
props.put(NAME, name);
// a loner is all this test needs
props.setProperty(MCAST_PORT, "0");
props.setProperty(LOCATORS, "");
DistributionConfig config = createSystem(props).getOriginalConfig();
assertEquals(name, config.getName());
}
@Test
public void testMemberTimeout() {
Properties props = new Properties();
int memberTimeout = 100;
props.put(MEMBER_TIMEOUT, String.valueOf(memberTimeout));
props.put(MCAST_PORT, "0");
DistributionConfig config = createSystem(props).getOriginalConfig();
assertEquals(memberTimeout, config.getMemberTimeout());
}
@Test
public void testMalformedLocators() {
Properties props = new Properties();
try {
// Totally bogus locator
props.put(LOCATORS, "14lasfk^5234");
createSystem(props);
fail("Should have thrown an IllegalArgumentException");
} catch (IllegalArgumentException ex) {
// pass...
}
try {
// missing port
props.put(LOCATORS, "localhost[");
createSystem(props);
fail("Should have thrown an IllegalArgumentException");
} catch (IllegalArgumentException ex) {
// pass...
}
try {
// Missing ]
props.put(LOCATORS, "localhost[234ty");
createSystem(props);
fail("Should have thrown an IllegalArgumentException");
} catch (IllegalArgumentException ex) {
// pass...
}
try {
// Malformed port
props.put(LOCATORS, "localhost[234ty]");
createSystem(props);
fail("Should have thrown an IllegalArgumentException");
} catch (IllegalArgumentException ex) {
// pass...
}
try {
// Malformed port in second locator
props.put(LOCATORS, "localhost[12345],localhost[sdf3");
createSystem(props);
fail("Should have thrown an IllegalArgumentException");
} catch (IllegalArgumentException ex) {
// pass...
}
}
/**
* Creates a new <code>DistributionConfigImpl</code> with the given locators string.
*
* @throws IllegalArgumentException If <code>locators</code> is malformed
* @since GemFire 4.0
*/
private void checkLocator(String locator) {
Properties props = new Properties();
props.put(LOCATORS, locator);
new DistributionConfigImpl(props);
}
/**
* Tests that both the traditional syntax ("host[port]") and post bug-32306 syntax ("host:port")
* can be used with locators.
*
* @since GemFire 4.0
*/
@Test
public void testLocatorSyntax() throws Exception {
String localhost = java.net.InetAddress.getLocalHost().getCanonicalHostName();
checkLocator(localhost + "[12345]");
checkLocator(localhost + ":12345");
String bindAddress = getHostAddress(java.net.InetAddress.getLocalHost());
if (bindAddress.indexOf(':') < 0) {
checkLocator(localhost + ":" + bindAddress + "[12345]");
}
checkLocator(localhost + "@" + bindAddress + "[12345]");
if (bindAddress.indexOf(':') < 0) {
checkLocator(localhost + ":" + bindAddress + ":12345");
}
if (localhost.indexOf(':') < 0) {
checkLocator(localhost + ":" + "12345");
}
}
/**
* Tests that getting the log level is what we expect.
*/
@Test
public void testGetLogLevel() {
Level logLevel = Level.FINER;
Properties props = new Properties();
// a loner is all this test needs
props.setProperty(MCAST_PORT, "0");
props.setProperty(LOCATORS, "");
props.put(LOG_LEVEL, logLevel.toString());
DistributionConfig config = createSystem(props).getConfig();
assertEquals(logLevel.intValue(), config.getLogLevel());
}
@Test
public void testInvalidLogLevel() {
try {
Properties props = new Properties();
props.put(LOG_LEVEL, "blah blah blah");
createSystem(props);
fail("Should have thrown an IllegalArgumentException");
} catch (IllegalArgumentException ex) {
// pass...
}
}
@Test
public void testGetStatisticSamplingEnabled() {
Properties props = new Properties();
// a loner is all this test needs
props.setProperty(MCAST_PORT, "0");
props.setProperty(LOCATORS, "");
props.put(STATISTIC_SAMPLING_ENABLED, "true");
DistributionConfig config = createSystem(props).getConfig();
assertEquals(true, config.getStatisticSamplingEnabled());
}
@Test
public void testGetStatisticSampleRate() {
String rate = String.valueOf(DistributionConfig.MIN_STATISTIC_SAMPLE_RATE);
Properties props = new Properties();
// a loner is all this test needs
props.setProperty(MCAST_PORT, "0");
props.setProperty(LOCATORS, "");
props.put(STATISTIC_SAMPLE_RATE, rate);
DistributionConfig config = createSystem(props).getConfig();
// The fix for 48228 causes the rate to be 1000 even if we try to set it less
assertEquals(1000, config.getStatisticSampleRate());
}
@Test
public void testMembershipPortRange() {
Properties props = new Properties();
props.setProperty(MCAST_PORT, "0");
props.setProperty(LOCATORS, "");
props.setProperty(MEMBERSHIP_PORT_RANGE, "45100-45200");
DistributionConfig config = createSystem(props).getConfig();
assertEquals(45100, config.getMembershipPortRange()[0]);
assertEquals(45200, config.getMembershipPortRange()[1]);
}
@Test
public void testBadMembershipPortRange() {
Properties props = new Properties();
props.setProperty(MCAST_PORT, "0");
props.setProperty(LOCATORS, "");
props.setProperty(MEMBERSHIP_PORT_RANGE, "5200-5100");
Object exception = null;
try {
createSystem(props).getConfig();
} catch (IllegalArgumentException expected) {
exception = expected;
}
assertNotNull("Expected an IllegalArgumentException", exception);
}
@Test
public void testGetStatisticArchiveFile() {
String fileName = "testGetStatisticArchiveFile";
Properties props = new Properties();
// a loner is all this test needs
props.setProperty(MCAST_PORT, "0");
props.setProperty(LOCATORS, "");
props.put(STATISTIC_ARCHIVE_FILE, fileName);
DistributionConfig config = createSystem(props).getConfig();
assertEquals(fileName, config.getStatisticArchiveFile().getName());
}
@Test
public void testGetCacheXmlFile() {
String fileName = "blah";
Properties props = new Properties();
// a loner is all this test needs
props.setProperty(MCAST_PORT, "0");
props.setProperty(LOCATORS, "");
props.put(CACHE_XML_FILE, fileName);
DistributionConfig config = createSystem(props).getConfig();
assertEquals(fileName, config.getCacheXmlFile().getPath());
}
@Test
public void testGetArchiveDiskSpaceLimit() {
String value = String.valueOf(DistributionConfig.MIN_ARCHIVE_DISK_SPACE_LIMIT);
Properties props = new Properties();
// a loner is all this test needs
props.setProperty(MCAST_PORT, "0");
props.setProperty(LOCATORS, "");
props.put(ARCHIVE_DISK_SPACE_LIMIT, value);
DistributionConfig config = createSystem(props).getConfig();
assertEquals(Integer.parseInt(value), config.getArchiveDiskSpaceLimit());
}
@Test
public void testInvalidArchiveDiskSpaceLimit() {
Properties props = new Properties();
props.put(ARCHIVE_DISK_SPACE_LIMIT, "blah");
try {
createSystem(props);
fail("Should have thrown an IllegalArgumentException");
} catch (IllegalArgumentException ex) {
// pass...
}
}
@Test
public void testGetArchiveFileSizeLimit() {
String value = String.valueOf(DistributionConfig.MIN_ARCHIVE_FILE_SIZE_LIMIT);
Properties props = new Properties();
// a loner is all this test needs
props.setProperty(MCAST_PORT, "0");
props.setProperty(LOCATORS, "");
props.put(ARCHIVE_FILE_SIZE_LIMIT, value);
DistributionConfig config = createSystem(props).getConfig();
assertEquals(Integer.parseInt(value), config.getArchiveFileSizeLimit());
}
@Test
public void testInvalidArchiveFileSizeLimit() {
Properties props = new Properties();
props.put(ARCHIVE_FILE_SIZE_LIMIT, "blah");
try {
createSystem(props);
fail("Should have thrown an IllegalArgumentException");
} catch (IllegalArgumentException ex) {
// pass...
}
}
@Test
public void testGetLogDiskSpaceLimit() {
String value = String.valueOf(DistributionConfig.MIN_LOG_DISK_SPACE_LIMIT);
Properties props = new Properties();
// a loner is all this test needs
props.setProperty(MCAST_PORT, "0");
props.setProperty(LOCATORS, "");
props.put(LOG_DISK_SPACE_LIMIT, value);
DistributionConfig config = createSystem(props).getConfig();
assertEquals(Integer.parseInt(value), config.getLogDiskSpaceLimit());
}
@Test
public void testInvalidLogDiskSpaceLimit() {
Properties props = new Properties();
props.put(LOG_DISK_SPACE_LIMIT, "blah");
try {
createSystem(props);
fail("Should have thrown an IllegalArgumentException");
} catch (IllegalArgumentException ex) {
// pass...
}
}
@Test
public void testGetLogFileSizeLimit() {
String value = String.valueOf(DistributionConfig.MIN_LOG_FILE_SIZE_LIMIT);
Properties props = new Properties();
// a loner is all this test needs
props.setProperty(MCAST_PORT, "0");
props.setProperty(LOCATORS, "");
props.put(LOG_FILE_SIZE_LIMIT, value);
DistributionConfig config = createSystem(props).getConfig();
assertEquals(Integer.parseInt(value), config.getLogFileSizeLimit());
}
@Test
public void testInvalidLogFileSizeLimit() {
Properties props = new Properties();
props.put(LOG_FILE_SIZE_LIMIT, "blah");
try {
createSystem(props);
fail("Should have thrown an IllegalArgumentException");
} catch (IllegalArgumentException ex) {
// pass...
}
}
@Test
public void testAccessingClosedDistributedSystem() {
Properties props = new Properties();
// a loner is all this test needs
props.setProperty(MCAST_PORT, "0");
props.setProperty(LOCATORS, "");
InternalDistributedSystem system = createSystem(props);
system.disconnect();
try {
system.getDistributionManager();
fail("Should have thrown an IllegalStateException");
} catch (DistributedSystemDisconnectedException ex) {
// pass...
}
try {
system.getLogWriter();
} catch (IllegalStateException ex) {
fail("Shouldn't have thrown an IllegalStateException");
}
}
@Test
public void testPropertySources() throws Exception {
// TODO: fix this test on Windows: the File renameTo and delete in finally fails on Windows
String os = System.getProperty("os.name");
if (os != null) {
if (os.indexOf("Windows") != -1) {
return;
}
}
File propFile = new File(GeodeGlossary.GEMFIRE_PREFIX + "properties");
boolean propFileExisted = propFile.exists();
File spropFile = new File("gfsecurity.properties");
boolean spropFileExisted = spropFile.exists();
try {
System.setProperty(GeodeGlossary.GEMFIRE_PREFIX + LOG_LEVEL, "finest");
Properties apiProps = new Properties();
apiProps.setProperty(GROUPS, "foo, bar");
{
if (propFileExisted) {
propFile.renameTo(new File(GeodeGlossary.GEMFIRE_PREFIX + "properties.sav"));
}
Properties fileProps = new Properties();
fileProps.setProperty("name", "myName");
FileWriter fw = new FileWriter(GeodeGlossary.GEMFIRE_PREFIX + "properties");
fileProps.store(fw, null);
fw.close();
}
{
if (spropFileExisted) {
spropFile.renameTo(new File("gfsecurity.properties.sav"));
}
Properties fileProps = new Properties();
fileProps.setProperty(STATISTIC_SAMPLE_RATE, "999");
FileWriter fw = new FileWriter("gfsecurity.properties");
fileProps.store(fw, null);
fw.close();
}
DistributionConfigImpl dci = new DistributionConfigImpl(apiProps);
assertEquals(null, dci.getAttributeSource(MCAST_PORT));
assertEquals(ConfigSource.api(), dci.getAttributeSource(GROUPS));
assertEquals(ConfigSource.sysprop(), dci.getAttributeSource(LOG_LEVEL));
assertEquals(ConfigSource.Type.FILE, dci.getAttributeSource("name").getType());
assertEquals(ConfigSource.Type.SECURE_FILE,
dci.getAttributeSource(STATISTIC_SAMPLE_RATE).getType());
} finally {
System.clearProperty(GeodeGlossary.GEMFIRE_PREFIX + "log-level");
propFile.delete();
if (propFileExisted) {
new File(GeodeGlossary.GEMFIRE_PREFIX + "properties.sav").renameTo(propFile);
}
spropFile.delete();
if (spropFileExisted) {
new File("gfsecurity.properties.sav").renameTo(spropFile);
}
}
}
/**
* Create a <Code>DistributedSystem</code> with a non-default name.
*/
@Test
public void testNonDefaultConnectionName() {
String name = "BLAH";
Properties props = new Properties();
// a loner is all this test needs
props.setProperty(MCAST_PORT, "0");
props.setProperty(LOCATORS, "");
props.setProperty(NAME, name);
createSystem(props);
}
@Test
public void testNonDefaultLogLevel() {
Level level = Level.FINE;
Properties props = new Properties();
// a loner is all this test needs
props.setProperty(MCAST_PORT, "0");
props.setProperty(LOCATORS, "");
props.put(LOG_LEVEL, level.toString());
InternalDistributedSystem system = createSystem(props);
assertEquals(level.intValue(), system.getConfig().getLogLevel());
assertEquals(level.intValue(), ((InternalLogWriter) system.getLogWriter()).getLogWriterLevel());
}
@Test
public void testStartLocator() {
Properties props = new Properties();
int unusedPort = getRandomAvailableTCPPort();
props.setProperty(MCAST_PORT, "0");
props.setProperty(START_LOCATOR, "localhost[" + unusedPort + "],server=false,peer=true");
deleteStateFile(unusedPort);
createSystem(props);
Collection locators = Locator.getLocators();
Assert.assertEquals(1, locators.size());
Locator locator = (Locator) locators.iterator().next();
// Assert.assertIndexDetailsEquals("127.0.0.1", locator.getBindAddress().getHostAddress());
// removed this check for ipv6 testing
Assert.assertEquals(unusedPort, locator.getPort().intValue());
deleteStateFile(unusedPort);
}
private void deleteStateFile(int port) {
File stateFile = new File("locator" + port + "state.dat");
if (stateFile.exists()) {
stateFile.delete();
}
}
@Test
public void testValidateProps() {
Properties props = new Properties();
props.setProperty(MCAST_PORT, "0");
props.setProperty(LOCATORS, "");
Config config1 = new DistributionConfigImpl(props, false);
MetricsService.Builder metricsSessionBuilder = mock(MetricsService.Builder.class);
when(metricsSessionBuilder.build(any())).thenReturn(mock(MetricsService.class));
InternalDistributedSystem sys =
new InternalDistributedSystem.Builder(config1.toProperties(), metricsSessionBuilder)
.build();
try {
props.put(MCAST_PORT, "1");
Config config2 = new DistributionConfigImpl(props, false);
try {
sys.validateSameProperties(config2.toProperties(), true);
fail("should have detected different mcast-ports");
} catch (IllegalStateException iex) {
// This passes the test
}
} finally {
sys.disconnect();
}
}
@Test
public void testDeprecatedSSLProps() {
// ssl-* props are copied to cluster-ssl-*.
Properties props = getCommonProperties();
props.setProperty(CLUSTER_SSL_ENABLED, "true");
Config config1 = new DistributionConfigImpl(props, false);
Properties props1 = config1.toProperties();
assertEquals("true", props1.getProperty(CLUSTER_SSL_ENABLED));
Config config2 = new DistributionConfigImpl(props1, false);
assertEquals(true, config1.sameAs(config2));
Properties props3 = new Properties(props1);
props3.setProperty(CLUSTER_SSL_ENABLED, "false");
Config config3 = new DistributionConfigImpl(props3, false);
assertEquals(false, config1.sameAs(config3));
}
@Test
public void testEmptySecurityAuthTokenProp() throws Exception {
Properties props = getCommonProperties();
props.setProperty(SECURITY_AUTH_TOKEN_ENABLED_COMPONENTS, "");
DistributionConfig config1 = new DistributionConfigImpl(props, false);
assertThat(config1.getSecurityAuthTokenEnabledComponents()).hasSize(0);
Properties securityProps = config1.getSecurityProps();
assertThat(securityProps.getProperty(SECURITY_AUTH_TOKEN_ENABLED_COMPONENTS)).isEqualTo("");
assertThat(config1.getSecurityAuthTokenEnabledComponents()).hasSize(0);
}
@Test
public void testSecurityAuthTokenProp() throws Exception {
Properties props = getCommonProperties();
props.setProperty(SECURITY_AUTH_TOKEN_ENABLED_COMPONENTS, "management");
DistributionConfig config1 = new DistributionConfigImpl(props, false);
assertThat(config1.getSecurityAuthTokenEnabledComponents()).containsExactly("MANAGEMENT");
Properties securityProps = config1.getSecurityProps();
assertThat(securityProps.getProperty(SECURITY_AUTH_TOKEN_ENABLED_COMPONENTS))
.isEqualTo("management");
assertThat(config1.getSecurityAuthTokenEnabledComponents()).containsExactly("MANAGEMENT");
}
@Test
public void testSSLEnabledComponents() {
Properties props = getCommonProperties();
props.setProperty(SSL_ENABLED_COMPONENTS, "cluster,server");
Config config1 = new DistributionConfigImpl(props, false);
assertEquals("cluster,server", config1.getAttribute(SSL_ENABLED_COMPONENTS));
}
@Rule
public ExpectedException illegalArgumentException = ExpectedException.none();
@Test(expected = IllegalArgumentException.class)
public void testSSLEnabledComponentsWrongComponentName() {
Properties props = getCommonProperties();
props.setProperty(SSL_ENABLED_COMPONENTS, "testing");
new DistributionConfigImpl(props, false);
illegalArgumentException.expect(IllegalArgumentException.class);
illegalArgumentException
.expectMessage("There is no registered component for the name: testing");
}
@Test(expected = IllegalArgumentException.class)
public void testSSLEnabledComponentsWithLegacyJMXSSLSettings() {
Properties props = getCommonProperties();
props.setProperty(SSL_ENABLED_COMPONENTS, "all");
props.setProperty(JMX_MANAGER_SSL_ENABLED, "true");
new DistributionConfigImpl(props, false);
illegalArgumentException.expect(IllegalArgumentException.class);
illegalArgumentException.expectMessage(
"When using ssl-enabled-components one cannot use any other SSL properties other than "
+ "cluster-ssl-* or the corresponding aliases");
}
@Test(expected = IllegalArgumentException.class)
public void testSSLEnabledComponentsWithLegacyGatewaySSLSettings() {
Properties props = getCommonProperties();
props.setProperty(SSL_ENABLED_COMPONENTS, "all");
props.setProperty(GATEWAY_SSL_ENABLED, "true");
new DistributionConfigImpl(props, false);
illegalArgumentException.expect(IllegalArgumentException.class);
illegalArgumentException.expectMessage(
"When using ssl-enabled-components one cannot use any other SSL properties other than "
+ "cluster-ssl-* or the corresponding aliases");
}
@Test(expected = IllegalArgumentException.class)
public void testSSLEnabledComponentsWithLegacyServerSSLSettings() {
Properties props = getCommonProperties();
props.setProperty(SSL_ENABLED_COMPONENTS, "all");
props.setProperty(SERVER_SSL_ENABLED, "true");
new DistributionConfigImpl(props, false);
illegalArgumentException.expect(IllegalArgumentException.class);
illegalArgumentException.expectMessage(
"When using ssl-enabled-components one cannot use any other SSL properties other than "
+ "cluster-ssl-* or the corresponding aliases");
}
@Test(expected = IllegalArgumentException.class)
public void testSSLEnabledComponentsWithLegacyHTTPServiceSSLSettings() {
Properties props = getCommonProperties();
props.setProperty(SSL_ENABLED_COMPONENTS, "all");
props.setProperty(HTTP_SERVICE_SSL_ENABLED, "true");
new DistributionConfigImpl(props, false);
illegalArgumentException.expect(IllegalArgumentException.class);
illegalArgumentException.expectMessage(
"When using ssl-enabled-components one cannot use any other SSL properties other than "
+ "cluster-ssl-* or the corresponding aliases");
}
@Test
public void usesSessionBuilderToCreateMetricsSession() {
MetricsService metricsSession = mock(MetricsService.class);
MetricsService.Builder metricsSessionBuilder = mock(MetricsService.Builder.class);
when(metricsSessionBuilder.build(any())).thenReturn(metricsSession);
createSystem(getCommonProperties(), metricsSessionBuilder);
verify(metricsSessionBuilder).build(system);
}
@Test
public void startsMetricsSession() {
MetricsService metricsSession = mock(MetricsService.class);
MetricsService.Builder metricsSessionBuilder = mock(MetricsService.Builder.class);
when(metricsSessionBuilder.build(any())).thenReturn(metricsSession);
when(metricsSession.getMeterRegistry()).thenReturn(mock(MeterRegistry.class));
createSystem(getCommonProperties(), metricsSessionBuilder);
verify(metricsSession).start();
}
@Test
public void getMeterRegistry_returnsMetricsSessionMeterRegistry() {
MeterRegistry sessionMeterRegistry = mock(MeterRegistry.class);
MetricsService metricsSession = mock(MetricsService.class);
when(metricsSession.getMeterRegistry()).thenReturn(sessionMeterRegistry);
MetricsService.Builder metricsSessionBuilder = mock(MetricsService.Builder.class);
when(metricsSessionBuilder.build(any())).thenReturn(metricsSession);
when(metricsSession.getMeterRegistry()).thenReturn(sessionMeterRegistry);
createSystem(getCommonProperties(), metricsSessionBuilder);
assertThat(system.getMeterRegistry()).isSameAs(sessionMeterRegistry);
}
private Properties getCommonProperties() {
Properties props = new Properties();
props.setProperty(MCAST_PORT, "0");
props.setProperty(LOCATORS, "");
return props;
}
public static String getHostAddress(InetAddress addr) {
String address = addr.getHostAddress();
if (addr instanceof Inet4Address || (!addr.isLinkLocalAddress() && !addr.isLoopbackAddress())) {
int idx = address.indexOf('%');
if (idx >= 0) {
address = address.substring(0, idx);
}
}
return address;
}
public static InetAddress getIPAddress() {
return Boolean.getBoolean("java.net.preferIPv6Addresses") ? getIPv6Address() : getIPv4Address();
}
protected static InetAddress getIPv4Address() {
InetAddress host = null;
try {
host = InetAddress.getLocalHost();
if (host instanceof Inet4Address) {
return host;
}
} catch (UnknownHostException e) {
String s = "Local host not found";
throw new RuntimeException(s, e);
}
try {
Enumeration i = NetworkInterface.getNetworkInterfaces();
while (i.hasMoreElements()) {
NetworkInterface ni = (NetworkInterface) i.nextElement();
Enumeration j = ni.getInetAddresses();
while (j.hasMoreElements()) {
InetAddress addr = (InetAddress) j.nextElement();
// gemfire won't form connections using link-local addresses
if (!addr.isLinkLocalAddress() && !addr.isLoopbackAddress()
&& (addr instanceof Inet4Address)) {
return addr;
}
}
}
String s = "IPv4 address not found";
throw new RuntimeException(s);
} catch (SocketException e) {
String s = "Problem reading IPv4 address";
throw new RuntimeException(s, e);
}
}
public static InetAddress getIPv6Address() {
try {
Enumeration i = NetworkInterface.getNetworkInterfaces();
while (i.hasMoreElements()) {
NetworkInterface ni = (NetworkInterface) i.nextElement();
Enumeration j = ni.getInetAddresses();
while (j.hasMoreElements()) {
InetAddress addr = (InetAddress) j.nextElement();
// gemfire won't form connections using link-local addresses
if (!addr.isLinkLocalAddress() && !addr.isLoopbackAddress()
&& (addr instanceof Inet6Address) && !isIPv6LinkLocalAddress((Inet6Address) addr)) {
return addr;
}
}
}
String s = "IPv6 address not found";
throw new RuntimeException(s);
} catch (SocketException e) {
String s = "Problem reading IPv6 address";
throw new RuntimeException(s, e);
}
}
/**
* Detect LinkLocal IPv6 address where the interface is missing, ie %[0-9].
*
* @see InetAddress#isLinkLocalAddress()
*/
private static boolean isIPv6LinkLocalAddress(Inet6Address addr) {
byte[] addrBytes = addr.getAddress();
return ((addrBytes[0] == (byte) 0xfe) && (addrBytes[1] == (byte) 0x80));
}
}