/*
 * 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));
  }
}
