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

import static org.apache.geode.distributed.AbstractLauncher.Status.NOT_RESPONDING;
import static org.apache.geode.distributed.AbstractLauncher.Status.ONLINE;
import static org.apache.geode.distributed.AbstractLauncher.Status.STOPPED;
import static org.apache.geode.distributed.ConfigurationProperties.DISABLE_AUTO_RECONNECT;
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.NAME;
import static org.apache.geode.internal.AvailablePortHelper.getRandomAvailableTCPPorts;
import static org.apache.geode.internal.net.SocketCreator.getLocalHost;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.catchThrowable;

import java.io.File;
import java.net.BindException;
import java.net.UnknownHostException;
import java.util.List;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import org.apache.geode.cache.Cache;
import org.apache.geode.cache.server.CacheServer;
import org.apache.geode.distributed.ServerLauncher.Builder;
import org.apache.geode.distributed.ServerLauncher.ServerState;
import org.apache.geode.internal.GemFireVersion;
import org.apache.geode.internal.process.ProcessControllerFactory;
import org.apache.geode.internal.process.ProcessType;

/**
 * Integration tests for using {@link ServerLauncher} as an in-process API within an existing JVM.
 *
 * @since GemFire 8.0
 */
public class ServerLauncherLocalIntegrationTest extends ServerLauncherLocalIntegrationTestCase {

  @Before
  public void setUpServerLauncherLocalIntegrationTest() {
    disconnectFromDS();
    System.setProperty(ProcessType.PROPERTY_TEST_PREFIX, getUniqueName() + "-");
    assertThat(new ProcessControllerFactory().isAttachAPIFound()).isTrue();
  }

  @After
  public void tearDownServerLauncherLocalIntegrationTest() {
    disconnectFromDS();
  }

  @Test
  public void usesLocatorPortAsDefaultPort() {
    launcher = givenServerLauncher();

    assertThat(launcher.getServerPort()).isEqualTo(defaultServerPort);
  }

  @Test
  public void startReturnsOnline() {
    launcher = givenServerLauncher();

    assertThat(launcher.start().getStatus()).isEqualTo(ONLINE);
  }

  @Test
  public void startWithPortUsesPort() {
    ServerLauncher launcher = startServer(newBuilder()
        .setDisableDefaultServer(false)
        .setServerPort(defaultServerPort));

    assertThat(launcher.getCache().getCacheServers().get(0).getPort()).isEqualTo(defaultServerPort);
  }

  @Test
  public void startWithPortZeroUsesAnEphemeralPort() {
    ServerLauncher launcher = startServer(newBuilder()
        .setDisableDefaultServer(false)
        .setServerPort(0));

    assertThat(launcher.getCache().getCacheServers().get(0).getPort()).isGreaterThan(0);
  }

  @Test
  public void startUsesBuilderValues() {
    ServerLauncher launcher = startServer(newBuilder()
        .set(DISABLE_AUTO_RECONNECT, "true"));

    Cache cache = launcher.getCache();
    assertThat(cache).isNotNull();

    DistributedSystem system = cache.getDistributedSystem();
    assertThat(system).isNotNull();
    assertThat(system.getProperties().getProperty(DISABLE_AUTO_RECONNECT)).isEqualTo("true");
    assertThat(system.getProperties().getProperty(LOG_LEVEL)).isEqualTo("config");
    assertThat(system.getProperties().getProperty(MCAST_PORT)).isEqualTo("0");
    assertThat(system.getProperties().getProperty(NAME)).isEqualTo(getUniqueName());
  }

  @Test
  public void startCreatesPidFile() {
    startServer();

    assertThat(getPidFile()).exists();
  }

  @Test
  public void pidFileContainsServerPid() {
    startServer();

    assertThat(getServerPid()).isEqualTo(localPid);
  }

  @Test
  public void startDeletesStaleControlFiles() {
    File stopRequestFile = givenControlFile(getProcessType().getStopRequestFileName());
    File statusRequestFile = givenControlFile(getProcessType().getStatusRequestFileName());
    File statusFile = givenControlFile(getProcessType().getStatusFileName());

    startServer();

    assertDeletionOf(stopRequestFile);
    assertDeletionOf(statusRequestFile);
    assertDeletionOf(statusFile);
  }

  @Test
  public void startOverwritesStalePidFile() {
    givenPidFile(fakePid);

    startServer();

    assertThat(getServerPid()).isNotEqualTo(fakePid);
  }

  @Test
  public void startWithDisableDefaultServerDoesNotUseDefaultPort() {
    givenServerPortIsFree(defaultServerPort);

    startServer(withDisableDefaultServer());

    assertThatServerPortIsFree(defaultServerPort);
  }

  @Test
  public void startWithDisableDefaultServerSucceedsWhenDefaultPortInUse() {
    givenServerPortInUse(defaultServerPort);

    startServer(withDisableDefaultServer());

    assertThatServerPortIsInUseBySocket(defaultServerPort);
  }

  @Test
  public void startWithServerPortOverridesPortInCacheXml() {
    int[] freePorts = getRandomAvailableTCPPorts(2);
    int cacheXmlPort = freePorts[0];
    int startPort = freePorts[1];
    givenCacheXmlFileWithServerPort(cacheXmlPort);

    launcher = startServer(newBuilder()
        .setServerPort(startPort));

    // server should use --server-port instead of port in cache.xml
    assertThatServerPortIsInUse(startPort);
    assertThatServerPortIsFree(cacheXmlPort);
    assertThat(Integer.valueOf(launcher.status().getPort())).isEqualTo(startPort);
  }

  @Test
  public void startWithServerPortOverridesDefaultWithCacheXml() {
    givenCacheXmlFile();

    launcher = awaitStart(newBuilder()
        .setServerPort(defaultServerPort));

    // verify server used --server-port instead of default
    assertThatServerPortIsInUse(defaultServerPort);
    assertThat(Integer.valueOf(launcher.status().getPort())).isEqualTo(defaultServerPort);
  }

  @Test
  public void startWithDefaultPortInUseFailsWithBindException() {
    givenServerPortInUse(defaultServerPort);
    launcher = newBuilder()
        .build();

    Throwable thrown = catchThrowable(() -> launcher.start());

    assertThat(thrown)
        .isInstanceOf(RuntimeException.class)
        .hasCauseInstanceOf(BindException.class);
  }

  @Test
  public void startWithServerPortInUseFailsWithBindException() {
    givenServerPortInUse(nonDefaultServerPort);
    launcher = newBuilder()
        .setServerPort(nonDefaultServerPort)
        .build();

    Throwable thrown = catchThrowable(() -> launcher.start());

    assertThat(thrown)
        .isInstanceOf(RuntimeException.class)
        .hasCauseInstanceOf(BindException.class);
  }

  @Test
  public void startWithParametersOverridesCacheXmlConfiguration() {
    int[] freePorts = getRandomAvailableTCPPorts(2);
    int xmlPort = freePorts[0];
    int serverPort = freePorts[1];
    int maxThreads = 100;
    int maxConnections = 1200;
    int maxMessageCount = 500000;
    int socketBufferSize = 342768;
    int messageTimeToLive = 120;
    String hostnameForClients = "hostName4Clients";
    String serverBindAddress = "127.0.0.1";

    ServerLauncher.Builder launcherBuilder = newBuilder()
        .setHostNameForClients(hostnameForClients)
        .setMaxConnections(maxConnections)
        .setMaxMessageCount(maxMessageCount)
        .setMaxThreads(maxThreads)
        .setMessageTimeToLive(messageTimeToLive)
        .setServerBindAddress(serverBindAddress)
        .setServerPort(serverPort)
        .setSocketBufferSize(socketBufferSize);

    givenCacheXmlFileWithServerProperties(xmlPort, CacheServer.DEFAULT_BIND_ADDRESS,
        CacheServer.DEFAULT_HOSTNAME_FOR_CLIENTS, CacheServer.DEFAULT_MAX_CONNECTIONS,
        CacheServer.DEFAULT_MAX_THREADS, CacheServer.DEFAULT_MAXIMUM_MESSAGE_COUNT,
        CacheServer.DEFAULT_MESSAGE_TIME_TO_LIVE, CacheServer.DEFAULT_SOCKET_BUFFER_SIZE);

    launcher = startServer(launcherBuilder);

    assertThatServerPortIsInUse(serverPort);
    assertThatServerPortIsFree(xmlPort);
    assertThat(Integer.valueOf(launcher.status().getPort())).isEqualTo(serverPort);

    List<CacheServer> servers = launcher.getCache().getCacheServers();
    assertThat(servers.size()).isEqualTo(1);

    CacheServer server = servers.get(0);
    assertThat(server.getBindAddress()).isEqualTo(serverBindAddress);
    assertThat(server.getHostnameForClients()).isEqualTo(hostnameForClients);
    assertThat(server.getMaxConnections()).isEqualTo(maxConnections);
    assertThat(server.getMaxThreads()).isEqualTo(maxThreads);
    assertThat(server.getMaximumMessageCount()).isEqualTo(maxMessageCount);
    assertThat(server.getMessageTimeToLive()).isEqualTo(messageTimeToLive);
    assertThat(server.getSocketBufferSize()).isEqualTo(socketBufferSize);
  }

  @Test
  public void statusForDisableDefaultServerHasEmptyPort() {
    givenServerPortIsFree(defaultServerPort);

    ServerState serverState = startServer(newBuilder()
        .setDisableDefaultServer(true))
            .status();

    assertThat(serverState.getPort()).isEqualTo("");
  }

  @Test
  public void statusWithPidReturnsOnlineWithDetails() throws UnknownHostException {
    givenRunningServer();

    ServerState serverState = new Builder()
        .setPid(localPid)
        .build()
        .status();

    assertThat(serverState.getClasspath()).isEqualTo(getClassPath());
    assertThat(serverState.getGemFireVersion()).isEqualTo(GemFireVersion.getGemFireVersion());
    assertThat(serverState.getHost()).isEqualTo(getLocalHost().getCanonicalHostName());
    assertThat(serverState.getJavaVersion()).isEqualTo(System.getProperty("java.version"));
    assertThat(serverState.getJvmArguments()).isEqualTo(getJvmArguments());
    assertThat(serverState.getLogFile()).isEqualTo(getLogFilePath());
    assertThat(serverState.getMemberName()).isEqualTo(getUniqueName());
    assertThat(serverState.getPid().intValue()).isEqualTo(localPid);
    assertThat(serverState.getStatus()).isEqualTo(ONLINE);
    assertThat(serverState.getUptime()).isGreaterThan(0);
    assertThat(serverState.getWorkingDirectory()).isEqualTo(getWorkingDirectoryPath());
  }

  @Test
  public void statusWithWorkingDirectoryReturnsOnlineWithDetails() throws UnknownHostException {
    givenRunningServer();

    ServerState serverState = new Builder()
        .setWorkingDirectory(getWorkingDirectoryPath())
        .build()
        .status();

    assertThat(serverState.getClasspath()).isEqualTo(getClassPath());
    assertThat(serverState.getGemFireVersion()).isEqualTo(GemFireVersion.getGemFireVersion());
    assertThat(serverState.getHost()).isEqualTo(getLocalHost().getCanonicalHostName());
    assertThat(serverState.getJavaVersion()).isEqualTo(System.getProperty("java.version"));
    assertThat(serverState.getJvmArguments()).isEqualTo(getJvmArguments());
    assertThat(serverState.getLogFile()).isEqualTo(getLogFilePath());
    assertThat(serverState.getMemberName()).isEqualTo(getUniqueName());
    assertThat(serverState.getPid().intValue()).isEqualTo(readPidFile());
    assertThat(serverState.getStatus()).isEqualTo(ONLINE);
    assertThat(serverState.getUptime()).isGreaterThan(0);
    assertThat(serverState.getWorkingDirectory()).isEqualTo(getWorkingDirectoryPath());
  }

  @Test
  public void statusWithEmptyPidFileThrowsIllegalArgumentException() {
    givenEmptyPidFile();
    ServerLauncher launcher = new Builder()
        .setWorkingDirectory(getWorkingDirectoryPath())
        .build();

    Throwable thrown = catchThrowable(() -> launcher.status());

    assertThat(thrown)
        .isInstanceOf(IllegalArgumentException.class)
        .hasMessageContaining("Invalid pid 'null' found in");
  }

  @Test
  public void statusWithEmptyWorkingDirectoryReturnsNotRespondingWithDetails()
      throws UnknownHostException {
    givenEmptyWorkingDirectory();

    ServerState serverState = new Builder()
        .setWorkingDirectory(getWorkingDirectoryPath())
        .build()
        .status();

    assertThat(serverState.getClasspath()).isNull();
    assertThat(serverState.getGemFireVersion()).isEqualTo(GemFireVersion.getGemFireVersion());
    assertThat(serverState.getHost()).isEqualTo(getLocalHost().getCanonicalHostName());
    assertThat(serverState.getJavaVersion()).isEqualTo(System.getProperty("java.version"));
    assertThat(serverState.getJvmArguments()).isEqualTo(getJvmArguments());
    assertThat(serverState.getLogFile()).isNull();
    assertThat(serverState.getMemberName()).isNull();
    assertThat(serverState.getPid()).isNull();
    assertThat(serverState.getStatus()).isEqualTo(NOT_RESPONDING);
    assertThat(serverState.getUptime().intValue()).isEqualTo(0);
    assertThat(serverState.getWorkingDirectory()).isEqualTo(getWorkingDirectoryPath());
  }

  /**
   * This test takes > 1 minute to run in {@link ServerLauncherLocalFileIntegrationTest}.
   */
  @Test
  public void statusWithStalePidFileReturnsNotResponding() {
    givenPidFile(fakePid);

    ServerState serverState = new Builder()
        .setWorkingDirectory(getWorkingDirectoryPath())
        .build()
        .status();

    assertThat(serverState.getStatus()).isEqualTo(NOT_RESPONDING);
  }

  @Test
  public void stopWithPidReturnsStopped() {
    givenRunningServer();

    ServerState serverState = new Builder()
        .setPid(localPid)
        .build()
        .stop();

    assertThat(serverState.getStatus()).isEqualTo(STOPPED);
  }

  @Test
  public void stopWithPidDeletesPidFile() {
    givenRunningServer(newBuilder().setDeletePidFileOnStop(true));

    new Builder()
        .setPid(localPid)
        .build()
        .stop();

    assertDeletionOf(getPidFile());
  }

  @Test
  public void stopWithWorkingDirectoryReturnsStopped() {
    givenRunningServer();

    ServerState serverState = new Builder()
        .setWorkingDirectory(getWorkingDirectoryPath())
        .build()
        .stop();

    assertThat(serverState.getStatus()).isEqualTo(STOPPED);
  }

  @Test
  public void stopWithWorkingDirectoryDeletesPidFile() {
    givenRunningServer(newBuilder().setDeletePidFileOnStop(true));

    new Builder()
        .setWorkingDirectory(getWorkingDirectoryPath())
        .build()
        .stop();

    assertDeletionOf(getPidFile());
  }

  @Test
  public void getCacheReturnsTheCache() {
    givenRunningServer();

    assertThat(launcher.getCache()).isInstanceOf(Cache.class);
  }
}
