You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@geode.apache.org by kl...@apache.org on 2017/08/11 17:12:04 UTC

[06/14] geode git commit: GEODE-3413: overhaul launcher and process classes and tests

http://git-wip-us.apache.org/repos/asf/geode/blob/894f3ee7/geode-core/src/test/java/org/apache/geode/distributed/ServerLauncherLocalIntegrationTest.java
----------------------------------------------------------------------
diff --git a/geode-core/src/test/java/org/apache/geode/distributed/ServerLauncherLocalIntegrationTest.java b/geode-core/src/test/java/org/apache/geode/distributed/ServerLauncherLocalIntegrationTest.java
index d525be2..29ddaaf 100755
--- a/geode-core/src/test/java/org/apache/geode/distributed/ServerLauncherLocalIntegrationTest.java
+++ b/geode-core/src/test/java/org/apache/geode/distributed/ServerLauncherLocalIntegrationTest.java
@@ -14,973 +14,327 @@
  */
 package org.apache.geode.distributed;
 
-import static org.apache.geode.distributed.ConfigurationProperties.*;
+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.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+
+import java.io.File;
+import java.net.BindException;
+import java.net.InetAddress;
+import java.util.Collections;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
 
 import org.apache.geode.cache.Cache;
-import org.apache.geode.cache.DataPolicy;
-import org.apache.geode.cache.Scope;
-import org.apache.geode.distributed.AbstractLauncher.Status;
 import org.apache.geode.distributed.ServerLauncher.Builder;
 import org.apache.geode.distributed.ServerLauncher.ServerState;
-import org.apache.geode.internal.AvailablePort;
-import org.apache.geode.internal.AvailablePortHelper;
 import org.apache.geode.internal.GemFireVersion;
-import org.apache.geode.internal.cache.AbstractCacheServer;
-import org.apache.geode.internal.cache.xmlcache.CacheCreation;
-import org.apache.geode.internal.cache.xmlcache.CacheXmlGenerator;
-import org.apache.geode.internal.cache.xmlcache.RegionAttributesCreation;
-import org.apache.geode.internal.net.SocketCreatorFactory;
 import org.apache.geode.internal.process.ProcessControllerFactory;
 import org.apache.geode.internal.process.ProcessType;
-import org.apache.geode.internal.process.ProcessUtils;
-import org.apache.geode.internal.security.SecurableCommunicationChannel;
 import org.apache.geode.test.junit.categories.IntegrationTest;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Ignore;
-import org.junit.Test;
-import org.junit.experimental.categories.Category;
-
-import java.io.File;
-import java.io.FileWriter;
-import java.io.PrintWriter;
-import java.lang.management.ManagementFactory;
-import java.net.BindException;
-import java.net.InetAddress;
-
-import static org.apache.geode.distributed.ConfigurationProperties.MCAST_PORT;
-import static org.hamcrest.CoreMatchers.equalTo;
-import static org.hamcrest.CoreMatchers.is;
-import static org.junit.Assert.*;
 
 /**
- * Integration tests for ServerLauncher as a local API in the local JVM.
+ * Integration tests for using {@link ServerLauncher} as an in-process API within an existing JVM.
  *
- * @see org.apache.geode.distributed.AbstractLauncher
- * @see org.apache.geode.distributed.ServerLauncher
- * @see org.apache.geode.distributed.ServerLauncher.Builder
- * @see org.apache.geode.distributed.ServerLauncher.ServerState
- * @see org.apache.geode.internal.AvailablePortHelper
  * @since GemFire 8.0
  */
 @Category(IntegrationTest.class)
-public class ServerLauncherLocalIntegrationTest extends AbstractServerLauncherIntegrationTestCase {
+public class ServerLauncherLocalIntegrationTest extends ServerLauncherLocalIntegrationTestCase {
 
   @Before
-  public final void setUpServerLauncherLocalTest() throws Exception {
+  public void setUpServerLauncherLocalIntegrationTest() throws Exception {
     disconnectFromDS();
-    System.setProperty(ProcessType.TEST_PREFIX_PROPERTY, getUniqueName() + "-");
+    System.setProperty(ProcessType.PROPERTY_TEST_PREFIX, getUniqueName() + "-");
+    assertThat(new ProcessControllerFactory().isAttachAPIFound()).isTrue();
   }
 
   @After
-  public final void tearDownServerLauncherLocalTest() throws Exception {
+  public void tearDownServerLauncherLocalIntegrationTest() throws Exception {
     disconnectFromDS();
   }
 
-  protected Status getExpectedStopStatusForNotRunning() {
-    return Status.NOT_RESPONDING;
+  @Test
+  public void usesLocatorPortAsDefaultPort() throws Exception {
+    launcher = givenServerLauncher();
+
+    assertThat(launcher.getServerPort()).isEqualTo(defaultServerPort);
   }
 
   @Test
-  public void testBuilderSetProperties() throws Throwable {
-    String rootFolder = this.temporaryFolder.getRoot().getCanonicalPath();
+  public void startReturnsOnline() throws Exception {
+    launcher = givenServerLauncher();
 
-    this.launcher = new Builder().setDisableDefaultServer(true).setForce(true)
-        .setMemberName(getUniqueName()).setWorkingDirectory(rootFolder)
-        .set(DISABLE_AUTO_RECONNECT, "true").set(LOG_LEVEL, "config").set(MCAST_PORT, "0").build();
+    assertThat(launcher.start().getStatus()).isEqualTo(ONLINE);
+  }
 
-    assertNotNull(this.launcher);
+  @Test
+  public void startWithPortUsesPort() throws Exception {
+    ServerLauncher launcher =
+        startServer(newBuilder().setDisableDefaultServer(false).setServerPort(defaultServerPort));
 
-    try {
-      assertEquals(Status.ONLINE, this.launcher.start().getStatus());
-      waitForServerToStart(this.launcher);
+    assertThat(launcher.getCache().getCacheServers().get(0).getPort()).isEqualTo(defaultServerPort);
+  }
 
-      final Cache cache = this.launcher.getCache();
+  @Test
+  public void startWithPortZeroUsesAnEphemeralPort() throws Exception {
+    ServerLauncher launcher =
+        startServer(newBuilder().setDisableDefaultServer(false).setServerPort(0));
 
-      assertNotNull(cache);
+    assertThat(launcher.getCache().getCacheServers().get(0).getPort()).isGreaterThan(0);
+  }
 
-      final DistributedSystem distributedSystem = cache.getDistributedSystem();
+  @Test
+  public void startUsesBuilderValues() throws Exception {
+    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());
+  }
 
-      assertNotNull(distributedSystem);
-      assertEquals("true", distributedSystem.getProperties().getProperty(DISABLE_AUTO_RECONNECT));
-      assertEquals("config", distributedSystem.getProperties().getProperty(LOG_LEVEL));
-      assertEquals("0", distributedSystem.getProperties().getProperty(MCAST_PORT));
-      assertEquals(getUniqueName(), distributedSystem.getProperties().getProperty(NAME));
+  @Test
+  public void startCreatesPidFile() throws Exception {
+    startServer();
 
-    } catch (Throwable e) {
-      this.errorCollector.addError(e);
-    }
+    assertThat(getPidFile()).exists();
+  }
+
+  @Test
+  public void pidFileContainsServerPid() throws Exception {
+    startServer();
 
-    try {
-      assertEquals(Status.STOPPED, this.launcher.stop().getStatus());
-      assertNull(this.launcher.getCache());
-    } catch (Throwable e) {
-      this.errorCollector.addError(e);
-    }
+    assertThat(getServerPid()).isEqualTo(localPid);
   }
 
   @Test
-  public void testIsAttachAPIFound() throws Exception {
-    final ProcessControllerFactory factory = new ProcessControllerFactory();
-    assertTrue(factory.isAttachAPIFound());
+  public void startDeletesStaleControlFiles() throws Exception {
+    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 testStartCreatesPidFile() throws Throwable {
-    String rootFolder = this.temporaryFolder.getRoot().getCanonicalPath();
-
-    // build and start the Server locally
-    final Builder builder = new Builder().setDisableDefaultServer(true)
-        .setMemberName(getUniqueName()).setRedirectOutput(true).setWorkingDirectory(rootFolder)
-        .set(LOG_LEVEL, "config").set(MCAST_PORT, "0");
-
-    this.launcher = builder.build();
-    assertNotNull(this.launcher);
-
-    try {
-      this.launcher.start();
-      waitForServerToStart(this.launcher);
-      assertEquals(Status.ONLINE, this.launcher.status().getStatus());
-
-      // validate the pid file and its contents
-      this.pidFile = new File(this.temporaryFolder.getRoot(), ProcessType.SERVER.getPidFileName());
-      assertTrue(this.pidFile.exists());
-      final int pid = readPid(this.pidFile);
-      assertTrue(pid > 0);
-      assertTrue(ProcessUtils.isProcessAlive(pid));
-      assertEquals(getPid(), pid);
-
-      assertEquals(Status.ONLINE, this.launcher.status().getStatus());
-
-    } catch (Throwable e) {
-      this.errorCollector.addError(e);
-    }
-
-    try {
-      assertEquals(Status.STOPPED, this.launcher.stop().getStatus());
-      waitForFileToDelete(this.pidFile);
-    } catch (Throwable e) {
-      this.errorCollector.addError(e);
-    }
+  public void startOverwritesStalePidFile() throws Exception {
+    givenPidFile(fakePid);
+
+    startServer();
+
+    assertThat(getServerPid()).isNotEqualTo(fakePid);
   }
 
   @Test
-  public void testStartDeletesStaleControlFiles() throws Throwable {
-    String rootFolder = this.temporaryFolder.getRoot().getCanonicalPath();
-
-    // create existing control files
-    this.stopRequestFile =
-        new File(this.temporaryFolder.getRoot(), ProcessType.SERVER.getStopRequestFileName());
-    this.stopRequestFile.createNewFile();
-    assertTrue(this.stopRequestFile.exists());
-
-    this.statusRequestFile =
-        new File(this.temporaryFolder.getRoot(), ProcessType.SERVER.getStatusRequestFileName());
-    this.statusRequestFile.createNewFile();
-    assertTrue(this.statusRequestFile.exists());
-
-    this.statusFile =
-        new File(this.temporaryFolder.getRoot(), ProcessType.SERVER.getStatusFileName());
-    this.statusFile.createNewFile();
-    assertTrue(this.statusFile.exists());
-
-    // build and start the server
-    final Builder builder = new Builder().setDisableDefaultServer(true)
-        .setMemberName(getUniqueName()).setRedirectOutput(true).setWorkingDirectory(rootFolder)
-        .set(LOG_LEVEL, "config").set(MCAST_PORT, "0");
-
-    assertFalse(builder.getForce());
-    this.launcher = builder.build();
-    assertFalse(this.launcher.isForcing());
-    this.launcher.start();
-
-    try {
-      waitForServerToStart(this.launcher);
-    } catch (Throwable e) {
-      this.errorCollector.addError(e);
-    }
-
-    try {
-      // validate the pid file and its contents
-      this.pidFile = new File(this.temporaryFolder.getRoot(), ProcessType.SERVER.getPidFileName());
-      assertTrue(this.pidFile.exists());
-      final int pid = readPid(this.pidFile);
-      assertTrue(pid > 0);
-      assertTrue(ProcessUtils.isProcessAlive(pid));
-      assertEquals(getPid(), pid);
-
-      // validate stale control files were deleted
-      assertFalse(this.stopRequestFile.exists());
-      assertFalse(this.statusRequestFile.exists());
-      assertFalse(this.statusFile.exists());
-
-    } catch (Throwable e) {
-      this.errorCollector.addError(e);
-    }
-
-    try {
-      assertEquals(Status.STOPPED, this.launcher.stop().getStatus());
-      waitForFileToDelete(this.pidFile);
-    } catch (Throwable e) {
-      this.errorCollector.addError(e);
-    }
+  public void startWithDisableDefaultServerDoesNotUseDefaultPort() throws Exception {
+    givenServerPortIsFree(defaultServerPort);
+
+    startServer(withDisableDefaultServer());
+
+    assertThatServerPortIsFree(defaultServerPort);
   }
 
   @Test
-  public void testStartOverwritesStalePidFile() throws Throwable {
-    String rootFolder = this.temporaryFolder.getRoot().getCanonicalPath();
-
-    // create existing pid file
-    this.pidFile = new File(this.temporaryFolder.getRoot(), ProcessType.SERVER.getPidFileName());
-    assertFalse("Integer.MAX_VALUE shouldn't be the same as local pid " + Integer.MAX_VALUE,
-        Integer.MAX_VALUE == ProcessUtils.identifyPid());
-    writePid(this.pidFile, Integer.MAX_VALUE);
-
-    // build and start the server
-    final Builder builder = new Builder().setDisableDefaultServer(true)
-        .setMemberName(getUniqueName()).setRedirectOutput(true).setWorkingDirectory(rootFolder)
-        .set(LOG_LEVEL, "config").set(MCAST_PORT, "0");
-
-    assertFalse(builder.getForce());
-    this.launcher = builder.build();
-    assertFalse(this.launcher.isForcing());
-    this.launcher.start();
-
-    try {
-      waitForServerToStart(this.launcher);
-    } catch (Throwable e) {
-      this.errorCollector.addError(e);
-    }
-
-    try {
-      // validate the pid file and its contents
-      assertTrue(this.pidFile.exists());
-      final int pid = readPid(this.pidFile);
-      assertTrue(pid > 0);
-      assertTrue(ProcessUtils.isProcessAlive(pid));
-      assertEquals(getPid(), pid);
-    } catch (Throwable e) {
-      this.errorCollector.addError(e);
-    }
-
-    try {
-      assertEquals(Status.STOPPED, this.launcher.stop().getStatus());
-      waitForFileToDelete(this.pidFile);
-    } catch (Throwable e) {
-      this.errorCollector.addError(e);
-    }
+  public void startWithDisableDefaultServerSucceedsWhenDefaultPortInUse() throws Exception {
+    givenServerPortInUse(defaultServerPort);
+
+    startServer(withDisableDefaultServer());
+
+    assertThatServerPortIsInUseBySocket(defaultServerPort);
   }
 
-  /**
-   * Confirms fix for #47778.
-   */
   @Test
-  public void testStartUsingDisableDefaultServerLeavesPortFree() throws Throwable {
-    String rootFolder = this.temporaryFolder.getRoot().getCanonicalPath();
-
-    // build and start the server
-    assertTrue(AvailablePort.isPortAvailable(this.serverPort, AvailablePort.SOCKET));
-
-    // build and start the server
-    final Builder builder = new Builder().setDisableDefaultServer(true)
-        .setMemberName(getUniqueName()).setRedirectOutput(true).setWorkingDirectory(rootFolder)
-        .set(LOG_LEVEL, "config").set(MCAST_PORT, "0");
-
-    this.launcher = builder.build();
-
-    // wait for server to start
-    try {
-      // if start succeeds without throwing exception then #47778 is fixed
-      this.launcher.start();
-      waitForServerToStart(this.launcher);
-
-      // validate the pid file and its contents
-      this.pidFile = new File(this.temporaryFolder.getRoot(), ProcessType.SERVER.getPidFileName());
-      assertTrue(this.pidFile.exists());
-      int pid = readPid(this.pidFile);
-      assertTrue(pid > 0);
-      assertTrue(ProcessUtils.isProcessAlive(pid));
-      assertEquals(getPid(), pid);
-
-      // verify server did not a port
-      assertTrue(AvailablePort.isPortAvailable(this.serverPort, AvailablePort.SOCKET));
-
-      final ServerState status = this.launcher.status();
-      final String portString = status.getPort();
-      assertEquals("Port should be \"\" instead of " + portString, "", portString);
-
-    } catch (Throwable e) {
-      this.errorCollector.addError(e);
-    }
-
-    // stop the server
-    try {
-      assertEquals(Status.STOPPED, this.launcher.stop().getStatus());
-      waitForFileToDelete(this.pidFile);
-    } catch (Throwable e) {
-      this.errorCollector.addError(e);
-    }
+  public void startWithServerPortOverridesPortInCacheXml() throws Exception {
+    int[] freePorts = getRandomAvailableTCPPorts(2);
+    int cacheXmlPort = freePorts[0];
+    int startPort = freePorts[1];
+    givenCacheXmlFileWithServerPort(cacheXmlPort);
+
+    launcher = startServer(new Builder().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);
   }
 
-  /**
-   * Confirms fix for #47778.
-   */
   @Test
-  public void testStartUsingDisableDefaultServerSkipsPortCheck() throws Throwable {
-    String rootFolder = this.temporaryFolder.getRoot().getCanonicalPath();
-
-    // generate one free port and then use TEST_OVERRIDE_DEFAULT_PORT_PROPERTY
-    this.socket = SocketCreatorFactory
-        .createNonDefaultInstance(false, false, null, null, System.getProperties())
-        .createServerSocket(this.serverPort, 50, null, -1);
-    assertFalse(AvailablePort.isPortAvailable(this.serverPort, AvailablePort.SOCKET));
-
-    // build and start the server
-    final Builder builder = new Builder().setDisableDefaultServer(true)
-        .setMemberName(getUniqueName()).setRedirectOutput(true).setWorkingDirectory(rootFolder)
-        .set(LOG_LEVEL, "config").set(MCAST_PORT, "0");
-
-    this.launcher = builder.build();
-
-    // wait for server to start
-    try {
-      // if start succeeds without throwing exception then #47778 is fixed
-      this.launcher.start();
-      waitForServerToStart(this.launcher);
-
-      // validate the pid file and its contents
-      this.pidFile = new File(this.temporaryFolder.getRoot(), ProcessType.SERVER.getPidFileName());
-      assertTrue(this.pidFile.exists());
-      int pid = readPid(this.pidFile);
-      assertTrue(pid > 0);
-      assertTrue(ProcessUtils.isProcessAlive(pid));
-      assertEquals(getPid(), pid);
-
-      final ServerState status = this.launcher.status();
-      final String portString = status.getPort();
-      assertEquals("Port should be \"\" instead of " + portString, "", portString);
-
-    } catch (Throwable e) {
-      this.errorCollector.addError(e);
-    }
-
-    // stop the server
-    try {
-      assertEquals(Status.STOPPED, this.launcher.stop().getStatus());
-      waitForFileToDelete(this.pidFile);
-    } catch (Throwable e) {
-      this.errorCollector.addError(e);
-    }
-
-    // verify port is still in use
-    this.errorCollector.checkThat(
-        AvailablePort.isPortAvailable(this.serverPort, AvailablePort.SOCKET), is(equalTo(false)));
+  public void startWithServerPortOverridesDefaultWithCacheXml() throws Exception {
+    givenCacheXmlFile();
+
+    launcher = awaitStart(new Builder().setMemberName(getUniqueName()).setRedirectOutput(true)
+        .setServerPort(defaultServerPort).setWorkingDirectory(getWorkingDirectoryPath())
+        .set(LOG_LEVEL, "config").set(MCAST_PORT, "0"));
+
+    // verify server used --server-port instead of default
+    assertThatServerPortIsInUse(defaultServerPort);
+    assertThat(Integer.valueOf(launcher.status().getPort())).isEqualTo(defaultServerPort);
   }
 
   @Test
-  @Ignore("Need to rewrite this without using dunit.Host")
-  public void testStartUsingForceOverwritesExistingPidFile()
-      throws Throwable {}/*
-                          * assertTrue(getUniqueName() + " is broken if PID == Integer.MAX_VALUE",
-                          * ProcessUtils.identifyPid() != Integer.MAX_VALUE);
-                          * 
-                          * // create existing pid file this.pidFile = new
-                          * File(ProcessType.SERVER.getPidFileName()); final int realPid =
-                          * Host.getHost(0).getVM(3).invoke(() -> ProcessUtils.identifyPid());
-                          * assertFalse(realPid == ProcessUtils.identifyPid());
-                          * writePid(this.pidFile, realPid);
-                          * 
-                          * // build and start the server final Builder builder = new Builder()
-                          * .setDisableDefaultServer(true) .setForce(true)
-                          * .setMemberName(getUniqueName()) .setRedirectOutput(true)
-                          * .set(DistributionConfig.ConfigurationProperties.MCAST_PORT, "0");
-                          * 
-                          * assertTrue(builder.getForce()); this.launcher = builder.build();
-                          * assertTrue(this.launcher.isForcing()); this.launcher.start();
-                          * 
-                          * // collect and throw the FIRST failure Throwable failure = null;
-                          * 
-                          * try { waitForServerToStart(this.launcher);
-                          * 
-                          * // validate the pid file and its contents
-                          * assertTrue(this.pidFile.exists()); final int pid =
-                          * readPid(this.pidFile); assertTrue(pid > 0);
-                          * assertTrue(ProcessUtils.isProcessAlive(pid));
-                          * assertIndexDetailsEquals(getPid(), pid);
-                          * 
-                          * // validate log file was created final String logFileName =
-                          * getUniqueName()+".log"; assertTrue("Log file should exist: " +
-                          * logFileName, new File(logFileName).exists());
-                          * 
-                          * } catch (Throwable e) { logger.error(e); if (failure == null) { failure
-                          * = e; } }
-                          * 
-                          * try { assertIndexDetailsEquals(Status.STOPPED,
-                          * this.launcher.stop().getStatus()); waitForFileToDelete(this.pidFile); }
-                          * catch (Throwable e) { logger.error(e); if (failure == null) { failure =
-                          * e; } }
-                          * 
-                          * if (failure != null) { throw failure; } } //
-                          * testStartUsingForceOverwritesExistingPidFile
-                          */
+  public void startWithDefaultPortInUseFailsWithBindException() throws Exception {
+    givenServerPortInUse(defaultServerPort);
+
+    launcher = new Builder().build();
+
+    assertThatThrownBy(() -> launcher.start()).isInstanceOf(RuntimeException.class)
+        .hasCauseInstanceOf(BindException.class);
+  }
 
-  /**
-   * Confirms part of fix for #47664
-   */
   @Test
-  public void testStartUsingServerPortOverridesCacheXml() throws Throwable {
-    // verifies part of the fix for #47664
-
-    String rootFolder = this.temporaryFolder.getRoot().getCanonicalPath();
-
-    // generate two free ports
-    final int[] freeTCPPorts = AvailablePortHelper.getRandomAvailableTCPPorts(2);
-    assertTrue(AvailablePort.isPortAvailable(freeTCPPorts[0], AvailablePort.SOCKET));
-    assertTrue(AvailablePort.isPortAvailable(freeTCPPorts[1], AvailablePort.SOCKET));
-
-    // write out cache.xml with one port
-    final CacheCreation creation = new CacheCreation();
-    final RegionAttributesCreation attrs = new RegionAttributesCreation(creation);
-    attrs.setScope(Scope.DISTRIBUTED_ACK);
-    attrs.setDataPolicy(DataPolicy.REPLICATE);
-    creation.createRegion(getUniqueName(), attrs);
-    creation.addCacheServer().setPort(freeTCPPorts[0]);
-
-    File cacheXmlFile = this.temporaryFolder.newFile(getUniqueName() + ".xml");
-    final PrintWriter pw = new PrintWriter(new FileWriter(cacheXmlFile), true);
-    CacheXmlGenerator.generate(creation, pw);
-    pw.close();
-
-    System.setProperty(CACHE_XML_FILE, cacheXmlFile.getCanonicalPath());
-
-    // start server
-    final Builder builder = new Builder().setMemberName(getUniqueName()).setRedirectOutput(true)
-        .setServerPort(freeTCPPorts[1]).setWorkingDirectory(rootFolder).set(LOG_LEVEL, "config")
-        .set(MCAST_PORT, "0");
-
-    this.launcher = builder.build();
-    this.launcher.start();
-
-    // wait for server to start up
-    try {
-      waitForServerToStart(this.launcher);
-
-      // validate the pid file and its contents
-      this.pidFile = new File(this.temporaryFolder.getRoot(), ProcessType.SERVER.getPidFileName());
-      assertTrue(this.pidFile.exists());
-      int pid = readPid(this.pidFile);
-      assertTrue(pid > 0);
-      assertTrue(ProcessUtils.isProcessAlive(pid));
-      assertEquals(getPid(), pid);
-
-      // verify server used --server-port instead of default or port in cache.xml
-      assertTrue(AvailablePort.isPortAvailable(freeTCPPorts[0], AvailablePort.SOCKET));
-      assertFalse(AvailablePort.isPortAvailable(freeTCPPorts[1], AvailablePort.SOCKET));
-
-      final ServerState status = this.launcher.status();
-      final String portString = status.getPort();
-      final int port = Integer.valueOf(portString);
-      assertEquals("Port should be " + freeTCPPorts[1] + " instead of " + port, freeTCPPorts[1],
-          port);
-
-    } catch (Throwable e) {
-      this.errorCollector.addError(e);
-    }
-
-    // stop the server
-    try {
-      assertEquals(Status.STOPPED, this.launcher.stop().getStatus());
-      waitForFileToDelete(this.pidFile);
-      assertFalse("PID file still exists!", pidFile.exists());
-    } catch (Throwable e) {
-      this.errorCollector.addError(e);
-    }
+  public void startWithServerPortInUseFailsWithBindException() throws Exception {
+    givenServerPortInUse(nonDefaultServerPort);
+
+    launcher = new Builder().setServerPort(nonDefaultServerPort).build();
+
+    assertThatThrownBy(() -> launcher.start()).isInstanceOf(RuntimeException.class)
+        .hasCauseInstanceOf(BindException.class);
+  }
+
+  @Test
+  public void statusForDisableDefaultServerHasEmptyPort() throws Exception {
+    givenServerPortIsFree(defaultServerPort);
+
+    ServerState serverState = startServer(newBuilder().setDisableDefaultServer(true)).status();
+
+    assertThat(serverState.getPort()).isEqualTo("");
+  }
+
+  @Test
+  public void statusWithPidReturnsOnlineWithDetails() throws Exception {
+    givenRunningServer();
+
+    ServerState serverState = new Builder().setPid(localPid).build().status();
+
+    assertThat(serverState.getStatus()).isEqualTo(ONLINE);
+    assertThat(serverState.getClasspath()).isEqualTo(getClassPath());
+    assertThat(serverState.getGemFireVersion()).isEqualTo(GemFireVersion.getGemFireVersion());
+    assertThat(serverState.getHost()).isEqualTo(InetAddress.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.getUptime()).isGreaterThan(0);
+    assertThat(serverState.getWorkingDirectory()).isEqualTo(getWorkingDirectoryPath());
   }
 
-  /**
-   * Confirms part of fix for #47664
-   */
   @Test
-  public void testStartUsingServerPortUsedInsteadOfDefaultCacheXml() throws Throwable {
-    String rootFolder = this.temporaryFolder.getRoot().getCanonicalPath();
-
-    // write out cache.xml with one port
-    final CacheCreation creation = new CacheCreation();
-    final RegionAttributesCreation attrs = new RegionAttributesCreation(creation);
-    attrs.setScope(Scope.DISTRIBUTED_ACK);
-    attrs.setDataPolicy(DataPolicy.REPLICATE);
-    creation.createRegion(getUniqueName(), attrs);
-    creation.addCacheServer();
-
-    File cacheXmlFile = this.temporaryFolder.newFile(getUniqueName() + ".xml");
-    final PrintWriter pw = new PrintWriter(new FileWriter(cacheXmlFile), true);
-    CacheXmlGenerator.generate(creation, pw);
-    pw.close();
-
-    System.setProperty(CACHE_XML_FILE, cacheXmlFile.getCanonicalPath());
-
-    // start server
-    final Builder builder = new Builder().setMemberName(getUniqueName()).setRedirectOutput(true)
-        .setServerPort(this.serverPort).setWorkingDirectory(rootFolder).set(LOG_LEVEL, "config")
-        .set(MCAST_PORT, "0");
-
-    this.launcher = builder.build();
-    this.launcher.start();
-
-    // wait for server to start up
-    try {
-      waitForServerToStart(this.launcher);
-
-      // validate the pid file and its contents
-      this.pidFile = new File(this.temporaryFolder.getRoot(), ProcessType.SERVER.getPidFileName());
-      assertTrue(this.pidFile.exists());
-      int pid = readPid(this.pidFile);
-      assertTrue(pid > 0);
-      assertTrue(ProcessUtils.isProcessAlive(pid));
-      assertEquals(getPid(), pid);
-
-      // verify server used --server-port instead of default
-      assertFalse(AvailablePort.isPortAvailable(this.serverPort, AvailablePort.SOCKET));
-
-      final int port = Integer.valueOf(this.launcher.status().getPort());
-      assertEquals("Port should be " + this.serverPort + " instead of " + port, this.serverPort,
-          port);
-
-    } catch (Throwable e) {
-      this.errorCollector.addError(e);
-    }
-
-    // stop the server
-    try {
-      assertEquals(Status.STOPPED, this.launcher.stop().getStatus());
-      waitForFileToDelete(this.pidFile);
-    } catch (Throwable e) {
-      this.errorCollector.addError(e);
-    }
+  public void statusWithWorkingDirectoryReturnsOnlineWithDetails() throws Exception {
+    givenRunningServer();
+
+    ServerState serverState =
+        new Builder().setWorkingDirectory(getWorkingDirectoryPath()).build().status();
+
+    assertThat(serverState.getStatus()).isEqualTo(ONLINE);
+    assertThat(serverState.getClasspath()).isEqualTo(getClassPath());
+    assertThat(serverState.getGemFireVersion()).isEqualTo(GemFireVersion.getGemFireVersion());
+    assertThat(serverState.getHost()).isEqualTo(InetAddress.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.getUptime()).isGreaterThan(0);
+    assertThat(serverState.getWorkingDirectory()).isEqualTo(getWorkingDirectoryPath());
   }
 
   @Test
-  public void testStartWithDefaultPortInUseFails() throws Throwable {
-    String rootFolder = this.temporaryFolder.getRoot().getCanonicalPath();
-
-    // generate one free port and then use TEST_OVERRIDE_DEFAULT_PORT_PROPERTY
-    this.socket =
-        SocketCreatorFactory.getSocketCreatorForComponent(SecurableCommunicationChannel.CLUSTER)
-            .createServerSocket(this.serverPort, 50, null, -1);
-    assertFalse(AvailablePort.isPortAvailable(this.serverPort, AvailablePort.SOCKET));
-
-    // build and start the server
-    final Builder builder = new Builder().setMemberName(getUniqueName()).setRedirectOutput(true)
-        .setWorkingDirectory(rootFolder).set(LOG_LEVEL, "config").set(MCAST_PORT, "0");
-
-    this.launcher = builder.build();
-
-    RuntimeException expected = null;
-    try {
-      this.launcher.start();
-
-      // why did it not fail like it's supposed to?
-      final String property =
-          System.getProperty(AbstractCacheServer.TEST_OVERRIDE_DEFAULT_PORT_PROPERTY);
-      assertNotNull(property);
-      assertEquals(this.serverPort, Integer.valueOf(property).intValue());
-      assertFalse(AvailablePort.isPortAvailable(this.serverPort, AvailablePort.SOCKET));
-
-      fail("Server port is " + this.launcher.getCache().getCacheServers().get(0).getPort());
-      fail("ServerLauncher start should have thrown RuntimeException caused by BindException");
-    } catch (RuntimeException e) {
-      expected = e;
-      assertNotNull(expected.getMessage());
-      // BindException text varies by platform
-    } catch (Throwable e) {
-      this.errorCollector.addError(e);
-    }
-
-    try {
-      assertNotNull(expected);
-      final Throwable cause = expected.getCause();
-      assertNotNull(cause);
-      assertTrue(cause instanceof BindException);
-      // BindException string varies by platform
-    } catch (Throwable e) {
-      this.errorCollector.addError(e);
-    }
-
-    try {
-      this.pidFile = new File(this.temporaryFolder.getRoot(), ProcessType.SERVER.getPidFileName());
-      assertFalse("Pid file should not exist: " + this.pidFile, this.pidFile.exists());
-
-      // creation of log file seems to be random -- look into why sometime
-      final String logFileName = getUniqueName() + ".log";
-      assertFalse("Log file should not exist: " + logFileName,
-          new File(this.temporaryFolder.getRoot(), logFileName).exists());
-
-    } catch (Throwable e) {
-      this.errorCollector.addError(e);
-    }
-
-    // just in case the launcher started...
-    ServerState status = null;
-    try {
-      status = this.launcher.stop();
-    } catch (Throwable t) {
-      // ignore
-    }
-
-    try {
-      waitForFileToDelete(this.pidFile);
-      assertEquals(getExpectedStopStatusForNotRunning(), status.getStatus());
-    } catch (Throwable e) {
-      this.errorCollector.addError(e);
-    }
+  public void statusWithEmptyPidFileThrowsIllegalArgumentException() throws Exception {
+    givenEmptyPidFile();
+
+    ServerLauncher launcher = new Builder().setWorkingDirectory(getWorkingDirectoryPath()).build();
+
+    assertThatThrownBy(() -> launcher.status()).isInstanceOf(IllegalArgumentException.class)
+        .hasMessageContaining("Invalid pid 'null' found in");
   }
 
   @Test
-  @Ignore("Need to rewrite this without using dunit.Host")
-  public void testStartWithExistingPidFileFails()
-      throws Throwable {}/*
-                          * // create existing pid file final int realPid =
-                          * Host.getHost(0).getVM(3).invoke(() -> ProcessUtils.identifyPid());
-                          * assertFalse("Remote pid shouldn't be the same as local pid " + realPid,
-                          * realPid == ProcessUtils.identifyPid());
-                          * 
-                          * this.pidFile = new File(ProcessType.SERVER.getPidFileName());
-                          * writePid(this.pidFile, realPid);
-                          * 
-                          * // build and start the server final Builder builder = new Builder()
-                          * .setDisableDefaultServer(true) .setMemberName(getUniqueName())
-                          * .setRedirectOutput(true) .set(logLevel, "config")
-                          * .set(DistributionConfig.ConfigurationProperties.MCAST_PORT, "0");
-                          * 
-                          * assertFalse(builder.getForce()); this.launcher = builder.build();
-                          * assertFalse(this.launcher.isForcing());
-                          * 
-                          * // collect and throw the FIRST failure Throwable failure = null;
-                          * RuntimeException expected = null;
-                          * 
-                          * try { this.launcher.start();
-                          * fail("ServerLauncher start should have thrown RuntimeException caused by FileAlreadyExistsException"
-                          * ); } catch (RuntimeException e) { expected = e;
-                          * assertNotNull(expected.getMessage()); assertTrue(expected.getMessage().
-                          * contains("A PID file already exists and a Server may be running in")); }
-                          * catch (Throwable e) { logger.error(e); if (failure == null) { failure =
-                          * e; } }
-                          * 
-                          * // just in case the launcher started... ServerState status = null; try {
-                          * status = this.launcher.stop(); } catch (Throwable t) { // ignore }
-                          * 
-                          * try { assertNotNull(expected); final Throwable cause =
-                          * expected.getCause(); assertNotNull(cause); assertTrue(cause instanceof
-                          * FileAlreadyExistsException);
-                          * assertTrue(cause.getMessage().contains("Pid file already exists: "));
-                          * assertTrue(cause.getMessage().contains("vf.gf.server.pid for process " +
-                          * realPid)); } catch (Throwable e) { logger.error(e); if (failure == null)
-                          * { failure = e; } }
-                          * 
-                          * try { delete(this.pidFile); final Status theStatus = status.getStatus();
-                          * assertFalse(theStatus == Status.STARTING); assertFalse(theStatus ==
-                          * Status.ONLINE); } catch (Throwable e) { logger.error(e); if (failure ==
-                          * null) { failure = e; } }
-                          * 
-                          * if (failure != null) { throw failure; } } //
-                          * testStartWithExistingPidFileFails
-                          */
+  public void statusWithEmptyWorkingDirectoryReturnsNotRespondingWithDetails() throws Exception {
+    givenEmptyWorkingDirectory();
+
+    ServerState serverState =
+        new Builder().setWorkingDirectory(getWorkingDirectoryPath()).build().status();
+
+    assertThat(serverState.getStatus()).isEqualTo(NOT_RESPONDING);
+    assertThat(serverState.getClasspath()).isNull();
+    assertThat(serverState.getGemFireVersion()).isEqualTo(GemFireVersion.getGemFireVersion());
+    assertThat(serverState.getHost()).isNull();
+    assertThat(serverState.getJavaVersion()).isNull();
+    assertThat(serverState.getJvmArguments()).isEqualTo(Collections.emptyList());
+    assertThat(serverState.getLogFile()).isNull();
+    assertThat(serverState.getMemberName()).isNull();
+    assertThat(serverState.getPid()).isNull();
+    assertThat(serverState.getUptime().intValue()).isEqualTo(0);
+    assertThat(serverState.getWorkingDirectory()).isEqualTo(getWorkingDirectoryPath());
+  }
 
   /**
-   * Confirms fix for #47665.
+   * This test takes > 1 minute to run in {@link ServerLauncherLocalFileIntegrationTest}.
    */
   @Test
-  public void testStartUsingServerPortInUseFails() throws Throwable {
-    String rootFolder = this.temporaryFolder.getRoot().getCanonicalPath();
-
-    // generate one free port and then use TEST_OVERRIDE_DEFAULT_PORT_PROPERTY
-    final int freeTCPPort = AvailablePort.getRandomAvailablePort(AvailablePort.SOCKET);
-    this.socket =
-        SocketCreatorFactory.getSocketCreatorForComponent(SecurableCommunicationChannel.CLUSTER)
-            .createServerSocket(freeTCPPort, 50, null, -1);
-
-    // build and start the server
-    final Builder builder = new Builder().setMemberName(getUniqueName()).setRedirectOutput(true)
-        .setServerPort(freeTCPPort).setWorkingDirectory(rootFolder).set(LOG_LEVEL, "config")
-        .set(MCAST_PORT, "0");
-
-    this.launcher = builder.build();
-
-    RuntimeException expected = null;
-    try {
-      this.launcher.start();
-      fail("ServerLauncher start should have thrown RuntimeException caused by BindException");
-    } catch (RuntimeException e) {
-      expected = e;
-      assertNotNull(expected.getMessage());
-      // BindException string varies by platform
-    } catch (Throwable e) {
-      this.errorCollector.addError(e);
-    }
-
-    try {
-      assertNotNull(expected);
-      final Throwable cause = expected.getCause();
-      assertNotNull(cause);
-      assertTrue(cause instanceof BindException);
-      // BindException string varies by platform
-    } catch (Throwable e) {
-      this.errorCollector.addError(e);
-    }
-
-    try {
-      this.pidFile = new File(this.temporaryFolder.getRoot(), ProcessType.SERVER.getPidFileName());
-      assertFalse("Pid file should not exist: " + this.pidFile, this.pidFile.exists());
-    } catch (Throwable e) {
-      this.errorCollector.addError(e);
-    }
-
-    // just in case the launcher started...
-    ServerState status = null;
-    try {
-      status = this.launcher.stop();
-    } catch (Throwable t) {
-      // ignore
-    }
-
-    try {
-      waitForFileToDelete(this.pidFile);
-      assertEquals(getExpectedStopStatusForNotRunning(), status.getStatus());
-    } catch (Throwable e) {
-      this.errorCollector.addError(e);
-    }
+  public void statusWithStalePidFileReturnsNotResponding() throws Exception {
+    givenPidFile(fakePid);
+
+    ServerState serverState =
+        new Builder().setWorkingDirectory(getWorkingDirectoryPath()).build().status();
+
+    assertThat(serverState.getStatus()).isEqualTo(NOT_RESPONDING);
   }
 
   @Test
-  public void testStatusUsingPid() throws Throwable {
-    String rootFolder = this.temporaryFolder.getRoot().getCanonicalPath();
-
-    // build and start the server
-    final Builder builder = new Builder().setDisableDefaultServer(true)
-        .setMemberName(getUniqueName()).setRedirectOutput(true).setWorkingDirectory(rootFolder)
-        .set(LOG_LEVEL, "config").set(MCAST_PORT, "0");
-
-    assertFalse(builder.getForce());
-    this.launcher = builder.build();
-    assertFalse(this.launcher.isForcing());
-
-    ServerLauncher pidLauncher = null;
-    try {
-      this.launcher.start();
-      waitForServerToStart(this.launcher);
-
-      this.pidFile = new File(this.temporaryFolder.getRoot(), ProcessType.SERVER.getPidFileName());
-      assertTrue(this.pidFile.exists());
-      final int pid = readPid(this.pidFile);
-      assertTrue(pid > 0);
-      assertEquals(ProcessUtils.identifyPid(), pid);
-
-      pidLauncher = new Builder().setPid(pid).build();
-      assertNotNull(pidLauncher);
-      assertFalse(pidLauncher.isRunning());
-
-      final ServerState actualStatus = pidLauncher.status();
-      assertNotNull(actualStatus);
-      assertEquals(Status.ONLINE, actualStatus.getStatus());
-      assertEquals(pid, actualStatus.getPid().intValue());
-      assertTrue(actualStatus.getUptime() > 0);
-      // getWorkingDirectory returns user.dir instead of rootFolder because test is starting Server
-      // in this process (to move logFile and pidFile into temp dir)
-      assertEquals(ManagementFactory.getRuntimeMXBean().getClassPath(),
-          actualStatus.getClasspath());
-      assertEquals(GemFireVersion.getGemFireVersion(), actualStatus.getGemFireVersion());
-      assertEquals(System.getProperty("java.version"), actualStatus.getJavaVersion());
-      assertEquals(InetAddress.getLocalHost().getCanonicalHostName(), actualStatus.getHost());
-      assertEquals(getUniqueName(), actualStatus.getMemberName());
-
-    } catch (Throwable e) {
-      this.errorCollector.addError(e);
-    }
-
-    if (pidLauncher == null) {
-      try {
-        assertEquals(Status.STOPPED, this.launcher.stop().getStatus());
-        waitForFileToDelete(this.pidFile);
-      } catch (Throwable e) {
-        this.errorCollector.addError(e);
-      }
-
-    } else {
-      try {
-        assertEquals(Status.STOPPED, pidLauncher.stop().getStatus());
-        waitForFileToDelete(this.pidFile);
-      } catch (Throwable e) {
-        this.errorCollector.addError(e);
-      }
-    }
+  public void stopWithPidReturnsStopped() throws Exception {
+    givenRunningServer();
+
+    ServerState serverState = new Builder().setPid(localPid).build().stop();
+
+    assertThat(serverState.getStatus()).isEqualTo(STOPPED);
   }
 
   @Test
-  public void testStatusUsingWorkingDirectory() throws Throwable {
-    String rootFolder = this.temporaryFolder.getRoot().getCanonicalPath();
-
-    // build and start the server
-    final Builder builder = new Builder().setDisableDefaultServer(true)
-        .setMemberName(getUniqueName()).setRedirectOutput(true).setWorkingDirectory(rootFolder)
-        .set(LOG_LEVEL, "config").set(MCAST_PORT, "0");
-
-    assertFalse(builder.getForce());
-    this.launcher = builder.build();
-    assertFalse(this.launcher.isForcing());
-
-    ServerLauncher dirLauncher = null;
-    try {
-      this.launcher.start();
-      waitForServerToStart(this.launcher);
-
-      this.pidFile = new File(this.temporaryFolder.getRoot(), ProcessType.SERVER.getPidFileName());
-      assertTrue(this.pidFile.exists());
-      final int pid = readPid(this.pidFile);
-      assertTrue(pid > 0);
-      assertEquals(ProcessUtils.identifyPid(), pid);
-
-      dirLauncher = new Builder().setWorkingDirectory(rootFolder).build();
-      assertNotNull(dirLauncher);
-      assertFalse(dirLauncher.isRunning());
-
-      final ServerState actualStatus = dirLauncher.status();
-      assertNotNull(actualStatus);
-      assertEquals(Status.ONLINE, actualStatus.getStatus());
-      assertEquals(pid, actualStatus.getPid().intValue());
-      assertTrue(actualStatus.getUptime() > 0);
-      // getWorkingDirectory returns user.dir instead of rootFolder because test is starting Server
-      // in this process (to move logFile and pidFile into temp dir)
-      assertEquals(ManagementFactory.getRuntimeMXBean().getClassPath(),
-          actualStatus.getClasspath());
-      assertEquals(GemFireVersion.getGemFireVersion(), actualStatus.getGemFireVersion());
-      assertEquals(System.getProperty("java.version"), actualStatus.getJavaVersion());
-      assertEquals(InetAddress.getLocalHost().getCanonicalHostName(), actualStatus.getHost());
-      assertEquals(getUniqueName(), actualStatus.getMemberName());
-
-    } catch (Throwable e) {
-      this.errorCollector.addError(e);
-    }
-
-    if (dirLauncher == null) {
-      try {
-        assertEquals(Status.STOPPED, this.launcher.stop().getStatus());
-        waitForFileToDelete(this.pidFile);
-      } catch (Throwable e) {
-        this.errorCollector.addError(e);
-      }
-
-    } else {
-      try {
-        assertEquals(Status.STOPPED, dirLauncher.stop().getStatus());
-        waitForFileToDelete(this.pidFile);
-      } catch (Throwable e) {
-        this.errorCollector.addError(e);
-      }
-    }
+  public void stopWithPidDeletesPidFile() throws Exception {
+    givenRunningServer(newBuilder().setDeletePidFileOnStop(true));
+
+    new Builder().setPid(localPid).build().stop();
+
+    assertDeletionOf(getPidFile());
   }
 
   @Test
-  public void testStopUsingPid() throws Throwable {
-    String rootFolder = this.temporaryFolder.getRoot().getCanonicalPath();
-
-    // build and start the server
-    final Builder builder = new Builder().setDisableDefaultServer(true)
-        .setMemberName(getUniqueName()).setRedirectOutput(true).setWorkingDirectory(rootFolder)
-        .set(LOG_LEVEL, "config").set(MCAST_PORT, "0");
-
-    assertFalse(builder.getForce());
-    this.launcher = builder.build();
-    assertFalse(this.launcher.isForcing());
-
-    ServerLauncher pidLauncher = null;
-
-    try {
-      this.launcher.start();
-      waitForServerToStart(this.launcher);
-
-      // validate the pid file and its contents
-      this.pidFile = new File(this.temporaryFolder.getRoot(), ProcessType.SERVER.getPidFileName());
-      assertTrue(this.pidFile.exists());
-      final int pid = readPid(this.pidFile);
-      assertTrue(pid > 0);
-      assertEquals(ProcessUtils.identifyPid(), pid);
-
-      pidLauncher = new Builder().setPid(pid).build();
-      assertNotNull(pidLauncher);
-      assertFalse(pidLauncher.isRunning());
-
-      // stop the server
-      final ServerState serverState = pidLauncher.stop();
-      assertNotNull(serverState);
-      assertEquals(Status.STOPPED, serverState.getStatus());
-
-    } catch (Throwable e) {
-      this.errorCollector.addError(e);
-    }
-
-    try {
-      this.launcher.stop();
-    } catch (Throwable e) {
-      // ignore
-    }
-
-    try {
-      // verify the PID file was deleted
-      waitForFileToDelete(this.pidFile);
-    } catch (Throwable e) {
-      this.errorCollector.addError(e);
-    }
+  public void stopWithWorkingDirectoryReturnsStopped() throws Exception {
+    givenRunningServer();
+
+    ServerState serverState =
+        new Builder().setWorkingDirectory(getWorkingDirectoryPath()).build().stop();
+
+    assertThat(serverState.getStatus()).isEqualTo(STOPPED);
   }
 
   @Test
-  public void testStopUsingWorkingDirectory() throws Throwable {
-    String rootFolder = this.temporaryFolder.getRoot().getCanonicalPath();
-
-    // build and start the server
-    final Builder builder = new Builder().setDisableDefaultServer(true)
-        .setMemberName(getUniqueName()).setRedirectOutput(true).setWorkingDirectory(rootFolder)
-        .set(LOG_LEVEL, "config").set(MCAST_PORT, "0");
-
-    assertFalse(builder.getForce());
-    this.launcher = builder.build();
-    assertFalse(this.launcher.isForcing());
-
-    ServerLauncher dirLauncher = null;
-    try {
-      this.launcher.start();
-      waitForServerToStart(this.launcher);
-
-      // validate the pid file and its contents
-      this.pidFile = new File(this.temporaryFolder.getRoot(), ProcessType.SERVER.getPidFileName());
-      assertTrue(this.pidFile.exists());
-      final int pid = readPid(this.pidFile);
-      assertTrue(pid > 0);
-      assertEquals(ProcessUtils.identifyPid(), pid);
-
-      dirLauncher = new Builder().setWorkingDirectory(rootFolder).build();
-      assertNotNull(dirLauncher);
-      assertFalse(dirLauncher.isRunning());
-
-      // stop the server
-      final ServerState serverState = dirLauncher.stop();
-      assertNotNull(serverState);
-      assertEquals(Status.STOPPED, serverState.getStatus());
-
-    } catch (Throwable e) {
-      this.errorCollector.addError(e);
-    }
-
-    try {
-      this.launcher.stop();
-    } catch (Throwable e) {
-      // ignore
-    }
-
-    try {
-      // verify the PID file was deleted
-      waitForFileToDelete(this.pidFile);
-    } catch (Throwable e) {
-      this.errorCollector.addError(e);
-    }
+  public void stopWithWorkingDirectoryDeletesPidFile() throws Exception {
+    givenRunningServer(newBuilder().setDeletePidFileOnStop(true));
+
+    new Builder().setWorkingDirectory(getWorkingDirectoryPath()).build().stop();
+
+    assertDeletionOf(getPidFile());
   }
 }

http://git-wip-us.apache.org/repos/asf/geode/blob/894f3ee7/geode-core/src/test/java/org/apache/geode/distributed/ServerLauncherLocalIntegrationTestCase.java
----------------------------------------------------------------------
diff --git a/geode-core/src/test/java/org/apache/geode/distributed/ServerLauncherLocalIntegrationTestCase.java b/geode-core/src/test/java/org/apache/geode/distributed/ServerLauncherLocalIntegrationTestCase.java
new file mode 100644
index 0000000..917b529
--- /dev/null
+++ b/geode-core/src/test/java/org/apache/geode/distributed/ServerLauncherLocalIntegrationTestCase.java
@@ -0,0 +1,26 @@
+/*
+ * 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;
+
+public class ServerLauncherLocalIntegrationTestCase extends ServerLauncherIntegrationTestCase {
+
+  protected ServerLauncher.Builder withDisableDefaultServer() {
+    return withDisableDefaultServer(true);
+  }
+
+  protected ServerLauncher.Builder withDisableDefaultServer(final boolean value) {
+    return newBuilder().setDisableDefaultServer(value);
+  }
+}

http://git-wip-us.apache.org/repos/asf/geode/blob/894f3ee7/geode-core/src/test/java/org/apache/geode/distributed/ServerLauncherRemoteFileIntegrationTest.java
----------------------------------------------------------------------
diff --git a/geode-core/src/test/java/org/apache/geode/distributed/ServerLauncherRemoteFileIntegrationTest.java b/geode-core/src/test/java/org/apache/geode/distributed/ServerLauncherRemoteFileIntegrationTest.java
index 5348b28..7b94e6f 100755
--- a/geode-core/src/test/java/org/apache/geode/distributed/ServerLauncherRemoteFileIntegrationTest.java
+++ b/geode-core/src/test/java/org/apache/geode/distributed/ServerLauncherRemoteFileIntegrationTest.java
@@ -14,29 +14,21 @@
  */
 package org.apache.geode.distributed;
 
-import static org.junit.Assert.*;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
 
-import java.io.File;
-import java.util.ArrayList;
-import java.util.List;
-
-import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.experimental.categories.Category;
 
-import org.apache.geode.distributed.AbstractLauncher.Status;
 import org.apache.geode.distributed.ServerLauncher.Builder;
 import org.apache.geode.internal.process.ProcessControllerFactory;
-import org.apache.geode.internal.process.ProcessStreamReader;
-import org.apache.geode.internal.process.ProcessType;
-import org.apache.geode.internal.process.ProcessUtils;
 import org.apache.geode.lang.AttachAPINotFoundException;
 import org.apache.geode.test.junit.categories.IntegrationTest;
 
 /**
- * Subclass of ServerLauncherRemoteDUnitTest which forces the code to not find the Attach API which
- * is in the JDK tools.jar. As a result ServerLauncher ends up using the FileProcessController
+ * Subclass of {@link ServerLauncherLocalIntegrationTest} which forces the code to not find the
+ * Attach API. As a result {@link ServerLauncher} ends up using the FileProcessController
  * implementation.
  * 
  * @since GemFire 8.0
@@ -47,179 +39,54 @@ public class ServerLauncherRemoteFileIntegrationTest extends ServerLauncherRemot
   @Before
   public void setUpServerLauncherRemoteFileTest() throws Exception {
     System.setProperty(ProcessControllerFactory.PROPERTY_DISABLE_ATTACH_API, "true");
+    assertThat(new ProcessControllerFactory().isAttachAPIFound()).isFalse();
   }
 
-  @After
-  public void tearDownServerLauncherRemoteFileTest() throws Exception {}
-
-  @Override
-  @Test
   /**
-   * Override and assert Attach API is NOT found
+   * Override to assert that STATUS with --pid throws AttachAPINotFoundException
    */
-  public void testIsAttachAPIFound() throws Exception {
-    final ProcessControllerFactory factory = new ProcessControllerFactory();
-    assertFalse(factory.isAttachAPIFound());
-  }
-
   @Override
   @Test
-  /**
-   * Override because FileProcessController cannot request status with PID
-   */
-  public void testStatusUsingPid() throws Throwable {
-    final List<String> jvmArguments = getJvmArguments();
-
-    final List<String> command = new ArrayList<String>();
-    command
-        .add(new File(new File(System.getProperty("java.home"), "bin"), "java").getCanonicalPath());
-    for (String jvmArgument : jvmArguments) {
-      command.add(jvmArgument);
-    }
-    command.add("-cp");
-    command.add(System.getProperty("java.class.path"));
-    command.add(ServerLauncher.class.getName());
-    command.add(ServerLauncher.Command.START.getName());
-    command.add(getUniqueName());
-    command.add("--disable-default-server");
-    command.add("--redirect-output");
-
-    this.process = new ProcessBuilder(command).directory(this.temporaryFolder.getRoot()).start();
-    this.processOutReader = new ProcessStreamReader.Builder(this.process)
-        .inputStream(this.process.getInputStream()).build().start();
-    this.processErrReader = new ProcessStreamReader.Builder(this.process)
-        .inputStream(this.process.getErrorStream()).build().start();
+  public void statusWithPidReturnsOnlineWithDetails() throws Exception {
+    givenRunningServer();
 
-    // wait for server to start
-    int pid = 0;
-    ServerLauncher pidLauncher = null;
-    this.launcher = new ServerLauncher.Builder()
-        .setWorkingDirectory(this.temporaryFolder.getRoot().getCanonicalPath()).build();
-    try {
-      waitForServerToStart();
-
-      // validate the pid file and its contents
-      this.pidFile = new File(this.temporaryFolder.getRoot(), ProcessType.SERVER.getPidFileName());
-      assertTrue(this.pidFile.exists());
-      pid = readPid(this.pidFile);
-      assertTrue(pid > 0);
-      assertTrue(ProcessUtils.isProcessAlive(pid));
-
-      // validate log file was created
-      final String logFileName = getUniqueName() + ".log";
-      assertTrue("Log file should exist: " + logFileName,
-          new File(this.temporaryFolder.getRoot(), logFileName).exists());
-
-      // use launcher with pid
-      pidLauncher = new Builder().setPid(pid).build();
-
-      assertNotNull(pidLauncher);
-      assertFalse(pidLauncher.isRunning());
-
-      // status with pid only should throw AttachAPINotFoundException
-      try {
-        pidLauncher.status();
-        fail("FileProcessController should have thrown AttachAPINotFoundException");
-      } catch (AttachAPINotFoundException e) {
-        // passed
-      }
-
-    } catch (Throwable e) {
-      this.errorCollector.addError(e);
-    }
-
-    // stop the server
-    try {
-      assertEquals(Status.STOPPED, this.launcher.stop().getStatus());
-      waitForPidToStop(pid, true);
-      waitForFileToDelete(this.pidFile);
-    } catch (Throwable e) {
-      this.errorCollector.addError(e);
-    } finally {
-      new File(ProcessType.SERVER.getStatusRequestFileName()).delete(); // TODO: delete
-    }
+    assertThatThrownBy(() -> new Builder().setPid(getServerPid()).build().status())
+        .isInstanceOf(AttachAPINotFoundException.class);
   }
 
-  @Override
-  @Test
   /**
-   * Override because FileProcessController cannot request stop with PID
+   * Override to assert that STOP with --pid throws AttachAPINotFoundException
    */
-  public void testStopUsingPid() throws Throwable {
-    final List<String> jvmArguments = getJvmArguments();
-
-    final List<String> command = new ArrayList<String>();
-    command
-        .add(new File(new File(System.getProperty("java.home"), "bin"), "java").getCanonicalPath());
-    for (String jvmArgument : jvmArguments) {
-      command.add(jvmArgument);
-    }
-    command.add("-cp");
-    command.add(System.getProperty("java.class.path"));
-    command.add(ServerLauncher.class.getName());
-    command.add(ServerLauncher.Command.START.getName());
-    command.add(getUniqueName());
-    command.add("--disable-default-server");
-    command.add("--redirect-output");
-
-    this.process = new ProcessBuilder(command).directory(this.temporaryFolder.getRoot()).start();
-    this.processOutReader =
-        new ProcessStreamReader.Builder(this.process).inputStream(this.process.getInputStream())
-            .inputListener(createLoggingListener("sysout", getUniqueName() + "#sysout")).build()
-            .start();
-    this.processErrReader =
-        new ProcessStreamReader.Builder(this.process).inputStream(this.process.getErrorStream())
-            .inputListener(createLoggingListener("syserr", getUniqueName() + "#syserr")).build()
-            .start();
-
-    // wait for server to start
-    int pid = 0;
-    ServerLauncher pidLauncher = null;
-    this.launcher = new ServerLauncher.Builder()
-        .setWorkingDirectory(this.temporaryFolder.getRoot().getCanonicalPath()).build();
-    try {
-      waitForServerToStart();
-
-      // validate the pid file and its contents
-      this.pidFile = new File(this.temporaryFolder.getRoot(), ProcessType.SERVER.getPidFileName());
-      assertTrue(this.pidFile.exists());
-      pid = readPid(this.pidFile);
-      assertTrue(pid > 0);
-      assertTrue(ProcessUtils.isProcessAlive(pid));
-
-      // validate log file was created
-      final String logFileName = getUniqueName() + ".log";
-      assertTrue("Log file should exist: " + logFileName,
-          new File(this.temporaryFolder.getRoot(), logFileName).exists());
-
-      // use launcher with pid
-      pidLauncher = new Builder().setPid(pid).build();
+  @Override
+  @Test
+  public void stopWithPidDeletesPidFile() throws Exception {
+    givenRunningServer();
 
-      assertNotNull(pidLauncher);
-      assertFalse(pidLauncher.isRunning());
+    assertThatThrownBy(() -> new Builder().setPid(getServerPid()).build().stop())
+        .isInstanceOf(AttachAPINotFoundException.class);
+  }
 
-      // stop with pid only should throw AttachAPINotFoundException
-      try {
-        pidLauncher.stop();
-        fail("FileProcessController should have thrown AttachAPINotFoundException");
-      } catch (AttachAPINotFoundException e) {
-        // passed
-      }
+  /**
+   * Override to assert that STOP with --pid throws AttachAPINotFoundException
+   */
+  @Override
+  @Test
+  public void stopWithPidReturnsStopped() throws Exception {
+    givenRunningServer();
 
-    } catch (Throwable e) {
-      this.errorCollector.addError(e);
-    }
+    assertThatThrownBy(() -> new Builder().setPid(getServerPid()).build().stop())
+        .isInstanceOf(AttachAPINotFoundException.class);
+  }
 
-    try {
-      // stop the server
-      assertEquals(Status.STOPPED, this.launcher.stop().getStatus());
-      waitForPidToStop(pid);
-      waitForFileToDelete(this.pidFile);
+  /**
+   * Override to assert that STOP with --pid throws AttachAPINotFoundException
+   */
+  @Override
+  @Test
+  public void stopWithPidStopsServerProcess() throws Exception {
+    givenRunningServer();
 
-    } catch (Throwable e) {
-      this.errorCollector.addError(e);
-    } finally {
-      new File(ProcessType.SERVER.getStopRequestFileName()).delete(); // TODO: delete
-    }
+    assertThatThrownBy(() -> new Builder().setPid(getServerPid()).build().stop())
+        .isInstanceOf(AttachAPINotFoundException.class);
   }
 }