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

[18/23] 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/AbstractLauncherTest.java
----------------------------------------------------------------------
diff --git a/geode-core/src/test/java/org/apache/geode/distributed/AbstractLauncherTest.java b/geode-core/src/test/java/org/apache/geode/distributed/AbstractLauncherTest.java
index 46d51e8..23395cc 100644
--- a/geode-core/src/test/java/org/apache/geode/distributed/AbstractLauncherTest.java
+++ b/geode-core/src/test/java/org/apache/geode/distributed/AbstractLauncherTest.java
@@ -14,253 +14,362 @@
  */
 package org.apache.geode.distributed;
 
+import static java.util.concurrent.TimeUnit.DAYS;
+import static java.util.concurrent.TimeUnit.HOURS;
+import static java.util.concurrent.TimeUnit.MILLISECONDS;
+import static java.util.concurrent.TimeUnit.MINUTES;
+import static java.util.concurrent.TimeUnit.SECONDS;
+import static org.apache.geode.distributed.AbstractLauncher.ServiceState.toDaysHoursMinutesSeconds;
 import static org.apache.geode.distributed.ConfigurationProperties.NAME;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertTrue;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.entry;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
 
+import java.net.URL;
+import java.util.Properties;
+
 import org.apache.commons.lang.StringUtils;
-import org.apache.geode.test.junit.categories.UnitTest;
 import org.junit.Test;
 import org.junit.experimental.categories.Category;
 
-import java.net.MalformedURLException;
-import java.net.URL;
-import java.util.Properties;
-import java.util.concurrent.TimeUnit;
+import org.apache.geode.test.junit.categories.UnitTest;
 
 /**
- * The AbstractLauncherTest class is a test suite of unit tests testing the contract and
- * functionality of the AbstractLauncher class.
- * <p/>
- * 
- * @see org.apache.geode.distributed.AbstractLauncher
- * @see org.junit.Assert
- * @see org.junit.Test
+ * Unit tests for {@link AbstractLauncher}.
+ *
  * @since GemFire 7.0
  */
 @Category(UnitTest.class)
 public class AbstractLauncherTest {
 
-  private AbstractLauncher<?> createAbstractLauncher(final String memberName,
-      final String memberId) {
-    return new FakeServiceLauncher(memberName, memberId);
-  }
-
   @Test
-  public void shouldBeMockable() throws Exception {
+  public void canBeMocked() throws Exception {
     AbstractLauncher mockAbstractLauncher = mock(AbstractLauncher.class);
     mockAbstractLauncher.setDebug(true);
     verify(mockAbstractLauncher, times(1)).setDebug(true);
   }
 
   @Test
-  public void testIsSet() {
-    final Properties properties = new Properties();
+  public void isSetReturnsFalseIfPropertyDoesNotExist() throws Exception {
+    assertThat(AbstractLauncher.isSet(new Properties(), NAME)).isFalse();
+  }
 
-    assertFalse(properties.containsKey(NAME));
-    assertFalse(AbstractLauncher.isSet(properties, NAME));
+  @Test
+  public void isSetReturnsFalseIfPropertyHasEmptyValue() throws Exception {
+    Properties properties = new Properties();
 
     properties.setProperty(NAME, "");
 
-    assertTrue(properties.containsKey(NAME));
-    assertFalse(AbstractLauncher.isSet(properties, NAME));
+    assertThat(AbstractLauncher.isSet(properties, NAME)).isFalse();
+  }
+
+  @Test
+  public void isSetReturnsFalseIfPropertyHasBlankValue() throws Exception {
+    Properties properties = new Properties();
 
     properties.setProperty(NAME, "  ");
 
-    assertTrue(properties.containsKey(NAME));
-    assertFalse(AbstractLauncher.isSet(properties, NAME));
+    assertThat(AbstractLauncher.isSet(properties, NAME)).isFalse();
+  }
+
+  @Test
+  public void isSetReturnsTrueIfPropertyHasRealValue() throws Exception {
+    Properties properties = new Properties();
+
+    properties.setProperty(NAME, "memberOne");
+
+    assertThat(AbstractLauncher.isSet(properties, NAME)).isTrue();
+  }
+
+  @Test
+  public void isSetKeyIsCaseSensitive() throws Exception {
+    Properties properties = new Properties();
 
     properties.setProperty(NAME, "memberOne");
 
-    assertTrue(AbstractLauncher.isSet(properties, NAME));
-    assertFalse(AbstractLauncher.isSet(properties, "NaMe"));
+    assertThat(AbstractLauncher.isSet(properties, "NaMe")).isFalse();
   }
 
   @Test
-  public void testLoadGemFirePropertiesWithNullURL() {
-    final Properties properties = AbstractLauncher.loadGemFireProperties(null);
-    assertNotNull(properties);
-    assertTrue(properties.isEmpty());
+  public void loadGemFirePropertiesWithNullURLReturnsEmptyProperties() throws Exception {
+    URL nullUrl = null;
+
+    Properties properties = AbstractLauncher.loadGemFireProperties(nullUrl);
+
+    assertThat(properties).isNotNull().isEmpty();
   }
 
   @Test
-  public void testLoadGemFirePropertiesWithNonExistingURL() throws MalformedURLException {
-    final Properties properties = AbstractLauncher
-        .loadGemFireProperties(new URL("file:///path/to/non_existing/gemfire.properties"));
-    assertNotNull(properties);
-    assertTrue(properties.isEmpty());
+  public void loadGemFirePropertiesWithNonExistingURLReturnsEmptyProperties() throws Exception {
+    URL nonExistingUrl = new URL("file:///path/to/non_existing/gemfire.properties");
+
+    Properties properties = AbstractLauncher.loadGemFireProperties(nonExistingUrl);
+
+    assertThat(properties).isNotNull().isEmpty();
   }
 
   @Test
-  public void testGetDistributedSystemProperties() {
+  public void getDistributedSystemPropertiesContainsMemberNameAsName() throws Exception {
     AbstractLauncher<?> launcher = createAbstractLauncher("memberOne", "1");
 
-    assertNotNull(launcher);
-    assertEquals("1", launcher.getMemberId());
-    assertEquals("memberOne", launcher.getMemberName());
+    Properties properties = launcher.getDistributedSystemProperties();
+
+    assertThat(properties).containsExactly(entry(NAME, "memberOne"));
+  }
+
+  @Test
+  public void getDistributedSystemPropertiesIsEmptyWhenMemberNameIsNull() throws Exception {
+    AbstractLauncher<?> launcher = createAbstractLauncher(null, "22");
 
-    Properties distributedSystemProperties = launcher.getDistributedSystemProperties();
+    Properties properties = launcher.getDistributedSystemProperties();
 
-    assertNotNull(distributedSystemProperties);
-    assertTrue(distributedSystemProperties.containsKey(NAME));
-    assertEquals("memberOne", distributedSystemProperties.getProperty(NAME));
+    assertThat(properties).isEmpty();
+  }
 
-    launcher = createAbstractLauncher(null, "22");
+  @Test
+  public void getDistributedSystemPropertiesIsEmptyWhenMemberNameIsEmpty() throws Exception {
+    AbstractLauncher<?> launcher = createAbstractLauncher(StringUtils.EMPTY, "333");
 
-    assertNotNull(launcher);
-    assertEquals("22", launcher.getMemberId());
-    assertNull(launcher.getMemberName());
+    Properties properties = launcher.getDistributedSystemProperties();
 
-    distributedSystemProperties = launcher.getDistributedSystemProperties();
+    assertThat(properties).isEmpty();
+  }
 
-    assertNotNull(distributedSystemProperties);
-    assertFalse(distributedSystemProperties.containsKey(NAME));
+  @Test
+  public void getDistributedSystemPropertiesIsEmptyWhenMemberNameIsBlank() throws Exception {
+    AbstractLauncher<?> launcher = createAbstractLauncher("  ", "4444");
 
-    launcher = createAbstractLauncher(StringUtils.EMPTY, "333");
+    Properties properties = launcher.getDistributedSystemProperties();
 
-    assertNotNull(launcher);
-    assertEquals("333", launcher.getMemberId());
-    assertEquals(StringUtils.EMPTY, launcher.getMemberName());
+    assertThat(properties).isEmpty();
+  }
 
-    distributedSystemProperties = launcher.getDistributedSystemProperties();
+  @Test
+  public void getDistributedSystemPropertiesIncludesDefaults() throws Exception {
+    AbstractLauncher<?> launcher = createAbstractLauncher("TestMember", "123");
+    Properties defaults = new Properties();
+    defaults.setProperty("testKey", "testValue");
 
-    assertNotNull(distributedSystemProperties);
-    assertFalse(distributedSystemProperties.containsKey(NAME));
+    Properties properties = launcher.getDistributedSystemProperties(defaults);
+
+    assertThat(properties.getProperty(NAME)).isEqualTo(launcher.getMemberName());
+    assertThat(properties.getProperty("testKey")).isEqualTo("testValue");
+  }
 
-    launcher = createAbstractLauncher("  ", "4444");
+  @Test
+  public void getMemberNameReturnsValue() throws Exception {
+    AbstractLauncher<?> launcher = createAbstractLauncher("memberOne", null);
 
-    assertNotNull(launcher);
-    assertEquals("4444", launcher.getMemberId());
-    assertEquals("  ", launcher.getMemberName());
+    assertThat(launcher.getMemberName()).isEqualTo("memberOne");
+  }
 
-    distributedSystemProperties = launcher.getDistributedSystemProperties();
+  @Test
+  public void getMemberNameReturnsEmptyIfEmpty() throws Exception {
+    AbstractLauncher<?> launcher = createAbstractLauncher(StringUtils.EMPTY, null);
 
-    assertNotNull(distributedSystemProperties);
-    assertFalse(distributedSystemProperties.containsKey(NAME));
+    assertThat(launcher.getMemberName()).isEqualTo(StringUtils.EMPTY);
   }
 
   @Test
-  public void testGetDistributedSystemPropertiesWithDefaults() {
-    AbstractLauncher<?> launcher = createAbstractLauncher("TestMember", "123");
+  public void getMemberNameReturnsBlankIfBlank() throws Exception {
+    AbstractLauncher<?> launcher = createAbstractLauncher(" ", null);
 
-    assertNotNull(launcher);
-    assertEquals("123", launcher.getMemberId());
-    assertEquals("TestMember", launcher.getMemberName());
+    assertThat(launcher.getMemberName()).isEqualTo(" ");
+  }
 
-    Properties defaults = new Properties();
+  @Test
+  public void getMemberNameReturnsSameNumberOfBlanks() throws Exception {
+    AbstractLauncher<?> launcher = createAbstractLauncher("   ", null);
 
-    defaults.setProperty("testKey", "testValue");
+    assertThat(launcher.getMemberName()).isEqualTo("   ");
+  }
+
+  @Test
+  public void getMemberIdReturnsValue() throws Exception {
+    AbstractLauncher<?> launcher = createAbstractLauncher(null, "123");
+
+    assertThat(launcher.getMemberId()).isEqualTo("123");
+  }
+
+  @Test
+  public void getMemberIdReturnsNullIfNull() throws Exception {
+    AbstractLauncher<?> launcher = createAbstractLauncher(null, null);
+
+    assertThat(launcher.getMemberId()).isNull();
+  }
+
+  @Test
+  public void getMemberIdReturnsEmptyIfEmpty() throws Exception {
+    AbstractLauncher<?> launcher = createAbstractLauncher(null, StringUtils.EMPTY);
+
+    assertThat(launcher.getMemberId()).isEqualTo(StringUtils.EMPTY);
+  }
 
-    Properties distributedSystemProperties = launcher.getDistributedSystemProperties(defaults);
+  @Test
+  public void getMemberIdReturnsBlankIfBlank() throws Exception {
+    AbstractLauncher<?> launcher = createAbstractLauncher(null, " ");
 
-    assertNotNull(distributedSystemProperties);
-    assertEquals(launcher.getMemberName(), distributedSystemProperties.getProperty(NAME));
-    assertEquals("testValue", distributedSystemProperties.getProperty("testKey"));
+    assertThat(launcher.getMemberId()).isEqualTo(" ");
   }
 
   @Test
-  public void testGetMember() {
+  public void getMemberIdReturnsSameNumberOfBlanks() throws Exception {
+    AbstractLauncher<?> launcher = createAbstractLauncher(null, "   ");
+
+    assertThat(launcher.getMemberId()).isEqualTo("   ");
+  }
+
+  @Test
+  public void getMemberPrefersMemberNameOverMemberId() throws Exception {
     AbstractLauncher<?> launcher = createAbstractLauncher("memberOne", "123");
 
-    assertNotNull(launcher);
-    assertEquals("123", launcher.getMemberId());
-    assertEquals("memberOne", launcher.getMemberName());
-    assertEquals("memberOne", launcher.getMember());
-
-    launcher = createAbstractLauncher(null, "123");
-
-    assertNotNull(launcher);
-    assertEquals("123", launcher.getMemberId());
-    assertNull(launcher.getMemberName());
-    assertEquals("123", launcher.getMember());
-
-    launcher = createAbstractLauncher(StringUtils.EMPTY, "123");
-
-    assertNotNull(launcher);
-    assertEquals("123", launcher.getMemberId());
-    assertEquals(StringUtils.EMPTY, launcher.getMemberName());
-    assertEquals("123", launcher.getMember());
-
-    launcher = createAbstractLauncher(" ", "123");
-
-    assertNotNull(launcher);
-    assertEquals("123", launcher.getMemberId());
-    assertEquals(" ", launcher.getMemberName());
-    assertEquals("123", launcher.getMember());
-
-    launcher = createAbstractLauncher(null, StringUtils.EMPTY);
-
-    assertNotNull(launcher);
-    assertEquals(StringUtils.EMPTY, launcher.getMemberId());
-    assertNull(launcher.getMemberName());
-    assertNull(launcher.getMember());
-
-    launcher = createAbstractLauncher(null, " ");
-
-    assertNotNull(launcher);
-    assertEquals(" ", launcher.getMemberId());
-    assertNull(launcher.getMemberName());
-    assertNull(launcher.getMember());
-  }
-
-  @Test
-  public void testAbstractLauncherServiceStateToDaysHoursMinutesSeconds() {
-    assertEquals("", AbstractLauncher.ServiceState.toDaysHoursMinutesSeconds(null));
-    assertEquals("0 seconds", AbstractLauncher.ServiceState.toDaysHoursMinutesSeconds(0l));
-    assertEquals("1 second", AbstractLauncher.ServiceState.toDaysHoursMinutesSeconds(1000l));
-    assertEquals("1 second", AbstractLauncher.ServiceState.toDaysHoursMinutesSeconds(1999l));
-    assertEquals("2 seconds", AbstractLauncher.ServiceState.toDaysHoursMinutesSeconds(2001l));
-    assertEquals("45 seconds", AbstractLauncher.ServiceState.toDaysHoursMinutesSeconds(45000l));
-    assertEquals("1 minute 0 seconds",
-        AbstractLauncher.ServiceState.toDaysHoursMinutesSeconds(60 * 1000l));
-    assertEquals("1 minute 1 second",
-        AbstractLauncher.ServiceState.toDaysHoursMinutesSeconds(61 * 1000l));
-    assertEquals("1 minute 30 seconds",
-        AbstractLauncher.ServiceState.toDaysHoursMinutesSeconds(90 * 1000l));
-    assertEquals("2 minutes 0 seconds",
-        AbstractLauncher.ServiceState.toDaysHoursMinutesSeconds(120 * 1000l));
-    assertEquals("2 minutes 1 second",
-        AbstractLauncher.ServiceState.toDaysHoursMinutesSeconds(121 * 1000l));
-    assertEquals("2 minutes 15 seconds",
-        AbstractLauncher.ServiceState.toDaysHoursMinutesSeconds(135 * 1000l));
-    assertEquals("1 hour 0 seconds",
-        AbstractLauncher.ServiceState.toDaysHoursMinutesSeconds(60 * 60 * 1000l));
-    assertEquals("1 hour 1 second",
-        AbstractLauncher.ServiceState.toDaysHoursMinutesSeconds(60 * 60 * 1000l + 1000l));
-    assertEquals("1 hour 15 seconds",
-        AbstractLauncher.ServiceState.toDaysHoursMinutesSeconds(60 * 60 * 1000l + 15000l));
-    assertEquals("1 hour 1 minute 0 seconds",
-        AbstractLauncher.ServiceState.toDaysHoursMinutesSeconds(60 * 61 * 1000l));
-    assertEquals("1 hour 1 minute 1 second",
-        AbstractLauncher.ServiceState.toDaysHoursMinutesSeconds(60 * 61 * 1000l + 1000l));
-    assertEquals("1 hour 1 minute 45 seconds",
-        AbstractLauncher.ServiceState.toDaysHoursMinutesSeconds(60 * 61 * 1000l + 45000l));
-    assertEquals("1 hour 2 minutes 0 seconds",
-        AbstractLauncher.ServiceState.toDaysHoursMinutesSeconds(60 * 62 * 1000l));
-    assertEquals("1 hour 5 minutes 1 second",
-        AbstractLauncher.ServiceState.toDaysHoursMinutesSeconds(60 * 65 * 1000l + 1000l));
-    assertEquals("1 hour 5 minutes 10 seconds",
-        AbstractLauncher.ServiceState.toDaysHoursMinutesSeconds(60 * 65 * 1000l + 10000l));
-    assertEquals("1 hour 59 minutes 11 seconds",
-        AbstractLauncher.ServiceState.toDaysHoursMinutesSeconds(60 * 119 * 1000l + 11000l));
-    assertEquals("1 day 1 hour 1 minute 1 second",
-        AbstractLauncher.ServiceState
-            .toDaysHoursMinutesSeconds(TimeUnit.DAYS.toMillis(1) + TimeUnit.HOURS.toMillis(1)
-                + TimeUnit.MINUTES.toMillis(1) + TimeUnit.SECONDS.toMillis(1)));
-    assertEquals("1 day 5 hours 15 minutes 45 seconds",
-        AbstractLauncher.ServiceState
-            .toDaysHoursMinutesSeconds(TimeUnit.DAYS.toMillis(1) + TimeUnit.HOURS.toMillis(5)
-                + TimeUnit.MINUTES.toMillis(15) + TimeUnit.SECONDS.toMillis(45)));
-    assertEquals("2 days 1 hour 30 minutes 1 second",
-        AbstractLauncher.ServiceState
-            .toDaysHoursMinutesSeconds(TimeUnit.DAYS.toMillis(2) + TimeUnit.HOURS.toMillis(1)
-                + TimeUnit.MINUTES.toMillis(30) + TimeUnit.SECONDS.toMillis(1)));
+    assertThat(launcher.getMember()).isEqualTo("memberOne").isEqualTo(launcher.getMemberName());
+  }
+
+  @Test
+  public void getMemberReturnsMemberIdIfMemberNameIsNull() throws Exception {
+    AbstractLauncher<?> launcher = createAbstractLauncher(null, "123");
+
+    assertThat(launcher.getMember()).isEqualTo("123").isEqualTo(launcher.getMemberId());
+  }
+
+  @Test
+  public void getMemberReturnsMemberIdIfMemberNameIsEmpty() throws Exception {
+    AbstractLauncher<?> launcher = createAbstractLauncher(StringUtils.EMPTY, "123");
+
+    assertThat(launcher.getMember()).isEqualTo("123").isEqualTo(launcher.getMemberId());
+  }
+
+  @Test
+  public void getMemberReturnsMemberIdIfMemberNameIsBlank() throws Exception {
+    AbstractLauncher<?> launcher = createAbstractLauncher(" ", "123");
+
+    assertThat(launcher.getMember()).isEqualTo("123").isEqualTo(launcher.getMemberId());
+  }
+
+  @Test
+  public void getMemberReturnsNullIfMemberIdIsNull() throws Exception {
+    AbstractLauncher<?> launcher = createAbstractLauncher(null, null);
+
+    assertThat(launcher.getMember()).isNull();
+  }
+
+  @Test
+  public void getMemberReturnNullIfMemberIdIsEmpty() throws Exception {
+    AbstractLauncher<?> launcher = createAbstractLauncher(null, StringUtils.EMPTY);
+
+    assertThat(launcher.getMember()).isNull();
+  }
+
+  @Test
+  public void getMemberReturnNullIfMemberIdIsBlank() throws Exception {
+    AbstractLauncher<?> launcher = createAbstractLauncher(null, " ");
+
+    assertThat(launcher.getMember()).isNull();
+  }
+
+  @Test
+  public void toDaysHoursMinutesSeconds_null_returnsEmptyString() throws Exception {
+    assertThat(toDaysHoursMinutesSeconds(null)).isEqualTo("");
+  }
+
+  @Test
+  public void toDaysHoursMinutesSeconds_milliseconds_returnsSecondsString() throws Exception {
+    assertThat(toDaysHoursMinutesSeconds(MILLISECONDS.toMillis(0))).isEqualTo("0 seconds");
+    assertThat(toDaysHoursMinutesSeconds(MILLISECONDS.toMillis(999))).isEqualTo("0 seconds");
+    assertThat(toDaysHoursMinutesSeconds(MILLISECONDS.toMillis(1000))).isEqualTo("1 second");
+    assertThat(toDaysHoursMinutesSeconds(MILLISECONDS.toMillis(1999))).isEqualTo("1 second");
+  }
+
+  @Test
+  public void toDaysHoursMinutesSeconds_seconds_returnsSecondsString() throws Exception {
+    assertThat(toDaysHoursMinutesSeconds(SECONDS.toMillis(0))).isEqualTo("0 seconds");
+    assertThat(toDaysHoursMinutesSeconds(SECONDS.toMillis(1))).isEqualTo("1 second");
+    assertThat(toDaysHoursMinutesSeconds(SECONDS.toMillis(2))).isEqualTo("2 seconds");
+    assertThat(toDaysHoursMinutesSeconds(SECONDS.toMillis(45))).isEqualTo("45 seconds");
+  }
+
+  @Test
+  public void toDaysHoursMinutesSeconds_minutes_returnsMinutesAndSecondsString() throws Exception {
+    assertThat(toDaysHoursMinutesSeconds(MINUTES.toMillis(1))).isEqualTo("1 minute 0 seconds");
+    assertThat(toDaysHoursMinutesSeconds(MINUTES.toMillis(2))).isEqualTo("2 minutes 0 seconds");
+  }
+
+  @Test
+  public void toDaysHoursMinutesSeconds_minutesAndSeconds_returnsMinutesAndSecondsString()
+      throws Exception {
+    assertThat(toDaysHoursMinutesSeconds(MINUTES.toMillis(1) + SECONDS.toMillis(1)))
+        .isEqualTo("1 minute 1 second");
+    assertThat(toDaysHoursMinutesSeconds(MINUTES.toMillis(1) + SECONDS.toMillis(30)))
+        .isEqualTo("1 minute 30 seconds");
+    assertThat(toDaysHoursMinutesSeconds(MINUTES.toMillis(2) + SECONDS.toMillis(1)))
+        .isEqualTo("2 minutes 1 second");
+    assertThat(toDaysHoursMinutesSeconds(MINUTES.toMillis(2) + SECONDS.toMillis(15)))
+        .isEqualTo("2 minutes 15 seconds");
+  }
+
+  @Test
+  public void toDaysHoursMinutesSeconds_hours_returnsHoursAndSecondsString() throws Exception {
+    assertThat(toDaysHoursMinutesSeconds(HOURS.toMillis(1))).isEqualTo("1 hour 0 seconds");
+  }
+
+  @Test
+  public void toDaysHoursMinutesSeconds_hoursAndSeconds_returnsHoursAndSecondsString()
+      throws Exception {
+    assertThat(toDaysHoursMinutesSeconds(HOURS.toMillis(1) + SECONDS.toMillis(1)))
+        .isEqualTo("1 hour 1 second");
+    assertThat(toDaysHoursMinutesSeconds(HOURS.toMillis(1) + SECONDS.toMillis(15)))
+        .isEqualTo("1 hour 15 seconds");
+  }
+
+  @Test
+  public void toDaysHoursMinutesSeconds_hoursAndMinutes_returnsHoursAndMinutesAndSecondsString()
+      throws Exception {
+    assertThat(toDaysHoursMinutesSeconds(HOURS.toMillis(1) + MINUTES.toMillis(1)))
+        .isEqualTo("1 hour 1 minute 0 seconds");
+    assertThat(toDaysHoursMinutesSeconds(HOURS.toMillis(1) + MINUTES.toMillis(2)))
+        .isEqualTo("1 hour 2 minutes 0 seconds");
+  }
+
+  @Test
+  public void toDaysHoursMinutesSeconds_hoursAndMinutesAndSeconds_returnsHoursAndMinutesAndSecondsString()
+      throws Exception {
+    assertThat(
+        toDaysHoursMinutesSeconds(HOURS.toMillis(1) + MINUTES.toMillis(1) + SECONDS.toMillis(1)))
+            .isEqualTo("1 hour 1 minute 1 second");
+    assertThat(
+        toDaysHoursMinutesSeconds(HOURS.toMillis(1) + MINUTES.toMillis(1) + SECONDS.toMillis(45)))
+            .isEqualTo("1 hour 1 minute 45 seconds");
+    assertThat(
+        toDaysHoursMinutesSeconds(HOURS.toMillis(1) + MINUTES.toMillis(5) + SECONDS.toMillis(1)))
+            .isEqualTo("1 hour 5 minutes 1 second");
+    assertThat(
+        toDaysHoursMinutesSeconds(HOURS.toMillis(1) + MINUTES.toMillis(5) + SECONDS.toMillis(10)))
+            .isEqualTo("1 hour 5 minutes 10 seconds");
+    assertThat(
+        toDaysHoursMinutesSeconds(HOURS.toMillis(1) + MINUTES.toMillis(59) + SECONDS.toMillis(11)))
+            .isEqualTo("1 hour 59 minutes 11 seconds");
+  }
+
+  @Test
+  public void toDaysHoursMinutesSeconds_daysAndHoursAndMinutesAndSeconds_returnsDaysAndHoursAndMinutesAndSecondsString()
+      throws Exception {
+    assertThat(toDaysHoursMinutesSeconds(
+        DAYS.toMillis(1) + HOURS.toMillis(1) + MINUTES.toMillis(1) + SECONDS.toMillis(1)))
+            .isEqualTo("1 day 1 hour 1 minute 1 second");
+    assertThat(toDaysHoursMinutesSeconds(
+        DAYS.toMillis(1) + HOURS.toMillis(5) + MINUTES.toMillis(15) + SECONDS.toMillis(45)))
+            .isEqualTo("1 day 5 hours 15 minutes 45 seconds");
+    assertThat(toDaysHoursMinutesSeconds(
+        DAYS.toMillis(2) + HOURS.toMillis(1) + MINUTES.toMillis(30) + SECONDS.toMillis(1)))
+            .isEqualTo("2 days 1 hour 30 minutes 1 second");
+  }
+
+  private AbstractLauncher<?> createAbstractLauncher(final String memberName,
+      final String memberId) {
+    return new FakeServiceLauncher(memberName, memberId);
   }
 
   private static class FakeServiceLauncher extends AbstractLauncher<String> {
@@ -303,5 +412,4 @@ public class AbstractLauncherTest {
       throw new UnsupportedOperationException("Not Implemented!");
     }
   }
-
 }

http://git-wip-us.apache.org/repos/asf/geode/blob/894f3ee7/geode-core/src/test/java/org/apache/geode/distributed/AbstractLocatorLauncherIntegrationTestCase.java
----------------------------------------------------------------------
diff --git a/geode-core/src/test/java/org/apache/geode/distributed/AbstractLocatorLauncherIntegrationTestCase.java b/geode-core/src/test/java/org/apache/geode/distributed/AbstractLocatorLauncherIntegrationTestCase.java
deleted file mode 100755
index 0908b74..0000000
--- a/geode-core/src/test/java/org/apache/geode/distributed/AbstractLocatorLauncherIntegrationTestCase.java
+++ /dev/null
@@ -1,135 +0,0 @@
-/*
- * 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 java.util.Arrays;
-import java.util.Collection;
-import java.util.concurrent.Callable;
-import java.util.function.IntSupplier;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.rules.ErrorCollector;
-import org.junit.rules.TemporaryFolder;
-
-import org.apache.geode.distributed.AbstractLauncher.Status;
-import org.apache.geode.distributed.LocatorLauncher.Builder;
-import org.apache.geode.distributed.LocatorLauncher.LocatorState;
-import org.apache.geode.distributed.internal.ClusterConfigurationService;
-import org.apache.geode.internal.AvailablePortHelper;
-import org.apache.geode.internal.DistributionLocator;
-import org.junit.runners.Parameterized;
-
-/**
- * @since GemFire 8.0
- */
-public abstract class AbstractLocatorLauncherIntegrationTestCase
-    extends AbstractLauncherIntegrationTestCase {
-
-  @Parameterized.Parameters
-  public static Collection<Object> data() {
-    return Arrays.asList(new Object[] {(IntSupplier) () -> 0,
-        (IntSupplier) () -> AvailablePortHelper.getRandomAvailableTCPPort()});
-  }
-
-  @Parameterized.Parameter
-  public IntSupplier portSupplier;
-
-  protected volatile int locatorPort;
-
-  protected volatile LocatorLauncher launcher;
-  protected volatile String workingDirectory;
-  protected volatile String clusterConfigDirectory;
-
-  @Rule
-  public ErrorCollector errorCollector = new ErrorCollector();
-
-  @Rule
-  public TemporaryFolder temporaryFolder = new TemporaryFolder();
-
-  @Before
-  public final void setUpAbstractLocatorLauncherIntegrationTestCase() throws Exception {
-    this.locatorPort = portSupplier.getAsInt();
-    System.setProperty(DistributionLocator.TEST_OVERRIDE_DEFAULT_PORT_PROPERTY,
-        String.valueOf(this.locatorPort));
-    this.workingDirectory = this.temporaryFolder.getRoot().getCanonicalPath();
-    this.clusterConfigDirectory = this.temporaryFolder
-        .newFolder(ClusterConfigurationService.CLUSTER_CONFIG_DISK_DIR_PREFIX + getUniqueName())
-        .getCanonicalPath();
-  }
-
-  @After
-  public final void tearDownAbstractLocatorLauncherIntegrationTestCase() throws Exception {
-    this.locatorPort = 0;
-    if (this.launcher != null) {
-      this.launcher.stop();
-      this.launcher = null;
-    }
-  }
-
-  /**
-   * Override if needed
-   */
-  protected Status getExpectedStopStatusForNotRunning() {
-    return Status.NOT_RESPONDING;
-  }
-
-  protected void waitForLocatorToStart(final LocatorLauncher launcher, int timeout, int interval,
-      boolean throwOnTimeout) throws Exception {
-    assertEventuallyTrue("waiting for process to start: " + launcher.status(),
-        new Callable<Boolean>() {
-          @Override
-          public Boolean call() throws Exception {
-            try {
-              final LocatorState LocatorState = launcher.status();
-              return (LocatorState != null && Status.ONLINE.equals(LocatorState.getStatus()));
-            } catch (RuntimeException e) {
-              return false;
-            }
-          }
-        }, timeout, interval);
-  }
-
-  protected void waitForLocatorToStart(final LocatorLauncher launcher, int timeout,
-      boolean throwOnTimeout) throws Exception {
-    waitForLocatorToStart(launcher, timeout, INTERVAL_MILLISECONDS, throwOnTimeout);
-  }
-
-  protected void waitForLocatorToStart(final LocatorLauncher launcher, boolean throwOnTimeout)
-      throws Exception {
-    waitForLocatorToStart(launcher, TIMEOUT_MILLISECONDS, INTERVAL_MILLISECONDS, throwOnTimeout);
-  }
-
-  protected void waitForLocatorToStart(final LocatorLauncher launcher) throws Exception {
-    waitForLocatorToStart(launcher, TIMEOUT_MILLISECONDS, INTERVAL_MILLISECONDS, true);
-  }
-
-  protected static void waitForLocatorToStart(int port, int timeout, int interval,
-      boolean throwOnTimeout) throws Exception {
-    final LocatorLauncher locatorLauncher = new Builder().setPort(port).build();
-    assertEventuallyTrue("Waiting for Locator in other process to start.", new Callable<Boolean>() {
-      @Override
-      public Boolean call() throws Exception {
-        try {
-          final LocatorState locatorState = locatorLauncher.status();
-          return (locatorState != null && Status.ONLINE.equals(locatorState.getStatus()));
-        } catch (RuntimeException e) {
-          return false;
-        }
-      }
-    }, timeout, interval);
-  }
-}

http://git-wip-us.apache.org/repos/asf/geode/blob/894f3ee7/geode-core/src/test/java/org/apache/geode/distributed/AbstractLocatorLauncherRemoteIntegrationTestCase.java
----------------------------------------------------------------------
diff --git a/geode-core/src/test/java/org/apache/geode/distributed/AbstractLocatorLauncherRemoteIntegrationTestCase.java b/geode-core/src/test/java/org/apache/geode/distributed/AbstractLocatorLauncherRemoteIntegrationTestCase.java
deleted file mode 100644
index 4117d25..0000000
--- a/geode-core/src/test/java/org/apache/geode/distributed/AbstractLocatorLauncherRemoteIntegrationTestCase.java
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * 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 org.apache.geode.distributed.internal.DistributionConfig;
-import org.apache.geode.internal.process.ProcessStreamReader;
-import org.junit.After;
-import org.junit.Before;
-
-import java.util.ArrayList;
-import java.util.List;
-
-public abstract class AbstractLocatorLauncherRemoteIntegrationTestCase
-    extends AbstractLocatorLauncherIntegrationTestCase {
-
-  protected volatile Process process;
-  protected volatile ProcessStreamReader processOutReader;
-  protected volatile ProcessStreamReader processErrReader;
-
-  @Before
-  public final void setUpAbstractLocatorLauncherRemoteIntegrationTestCase() throws Exception {}
-
-  @After
-  public final void tearDownAbstractLocatorLauncherRemoteIntegrationTestCase() throws Exception {
-    if (this.process != null) {
-      this.process.destroy();
-      this.process = null;
-    }
-    if (this.processOutReader != null && this.processOutReader.isRunning()) {
-      this.processOutReader.stop();
-    }
-    if (this.processErrReader != null && this.processErrReader.isRunning()) {
-      this.processErrReader.stop();
-    }
-  }
-
-  /**
-   * Override as needed.
-   */
-  protected List<String> getJvmArguments() {
-    final List<String> jvmArguments = new ArrayList<String>();
-    jvmArguments.add("-D" + DistributionConfig.GEMFIRE_PREFIX + "log-level=config");
-    return jvmArguments;
-  }
-
-  /**
-   * Remove final if a test needs to override.
-   */
-  protected AbstractLauncher.Status getExpectedStopStatusForNotRunning() {
-    return AbstractLauncher.Status.NOT_RESPONDING;
-  }
-
-}

http://git-wip-us.apache.org/repos/asf/geode/blob/894f3ee7/geode-core/src/test/java/org/apache/geode/distributed/AbstractServerLauncherIntegrationTestCase.java
----------------------------------------------------------------------
diff --git a/geode-core/src/test/java/org/apache/geode/distributed/AbstractServerLauncherIntegrationTestCase.java b/geode-core/src/test/java/org/apache/geode/distributed/AbstractServerLauncherIntegrationTestCase.java
deleted file mode 100755
index 0e52dfc..0000000
--- a/geode-core/src/test/java/org/apache/geode/distributed/AbstractServerLauncherIntegrationTestCase.java
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- * 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 org.apache.geode.distributed.AbstractLauncher.Status;
-import org.apache.geode.distributed.ServerLauncher.ServerState;
-import org.apache.geode.distributed.internal.DistributionConfig;
-import org.apache.geode.internal.AvailablePortHelper;
-import org.apache.geode.internal.cache.AbstractCacheServer;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.rules.ErrorCollector;
-import org.junit.rules.TemporaryFolder;
-
-import java.util.concurrent.Callable;
-
-import static org.apache.geode.distributed.ConfigurationProperties.MCAST_PORT;
-import static org.junit.Assert.assertNotNull;
-
-/**
- * @since GemFire 8.0
- */
-public abstract class AbstractServerLauncherIntegrationTestCase
-    extends AbstractLauncherIntegrationTestCase {
-
-  protected volatile int serverPort;
-  protected volatile ServerLauncher launcher;
-  protected volatile String workingDirectory;
-
-  @Rule
-  public ErrorCollector errorCollector = new ErrorCollector();
-
-  @Rule
-  public TemporaryFolder temporaryFolder = new TemporaryFolder();
-
-  @Before
-  public final void setUpServerLauncherTest() throws Exception {
-    System.setProperty(DistributionConfig.GEMFIRE_PREFIX + MCAST_PORT, Integer.toString(0));
-    final int port = AvailablePortHelper.getRandomAvailableTCPPort();
-    System.setProperty(AbstractCacheServer.TEST_OVERRIDE_DEFAULT_PORT_PROPERTY,
-        String.valueOf(port));
-    this.serverPort = port;
-    this.workingDirectory = this.temporaryFolder.getRoot().getCanonicalPath();
-  }
-
-  @After
-  public final void tearDownServerLauncherTest() throws Exception {
-    this.serverPort = 0;
-    if (this.launcher != null) {
-      this.launcher.stop();
-      this.launcher = null;
-    }
-  }
-
-  protected void waitForServerToStart(final ServerLauncher launcher, int timeout, int interval,
-      boolean throwOnTimeout) throws Exception {
-    assertEventuallyTrue("waiting for local Server to start: " + launcher.status(),
-        new Callable<Boolean>() {
-          @Override
-          public Boolean call() throws Exception {
-            try {
-              final ServerState serverState = launcher.status();
-              assertNotNull(serverState);
-              return Status.ONLINE.equals(serverState.getStatus());
-            } catch (RuntimeException e) {
-              return false;
-            }
-          }
-        }, timeout, interval);
-  }
-
-  protected void waitForServerToStart(final ServerLauncher launcher, boolean throwOnTimeout)
-      throws Exception {
-    waitForServerToStart(launcher, TIMEOUT_MILLISECONDS, INTERVAL_MILLISECONDS, throwOnTimeout);
-  }
-
-  protected void waitForServerToStart(final ServerLauncher launcher, int timeout,
-      boolean throwOnTimeout) throws Exception {
-    waitForServerToStart(launcher, timeout, INTERVAL_MILLISECONDS, throwOnTimeout);
-  }
-
-  protected void waitForServerToStart(final ServerLauncher launcher) throws Exception {
-    waitForServerToStart(launcher, TIMEOUT_MILLISECONDS, INTERVAL_MILLISECONDS, true);
-  }
-}

http://git-wip-us.apache.org/repos/asf/geode/blob/894f3ee7/geode-core/src/test/java/org/apache/geode/distributed/AbstractServerLauncherRemoteIntegrationTestCase.java
----------------------------------------------------------------------
diff --git a/geode-core/src/test/java/org/apache/geode/distributed/AbstractServerLauncherRemoteIntegrationTestCase.java b/geode-core/src/test/java/org/apache/geode/distributed/AbstractServerLauncherRemoteIntegrationTestCase.java
deleted file mode 100644
index b50b77a..0000000
--- a/geode-core/src/test/java/org/apache/geode/distributed/AbstractServerLauncherRemoteIntegrationTestCase.java
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- * 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 org.apache.geode.distributed.internal.DistributionConfig;
-import org.apache.geode.internal.process.ProcessStreamReader;
-import org.junit.After;
-import org.junit.Before;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.concurrent.Callable;
-
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.fail;
-
-public abstract class AbstractServerLauncherRemoteIntegrationTestCase
-    extends AbstractServerLauncherIntegrationTestCase {
-
-  protected volatile Process process;
-  protected volatile ProcessStreamReader processOutReader;
-  protected volatile ProcessStreamReader processErrReader;
-
-  @Before
-  public final void setUpAbstractServerLauncherRemoteIntegrationTestCase() throws Exception {}
-
-  @After
-  public final void tearDownAbstractServerLauncherRemoteIntegrationTestCase() throws Exception {
-    if (this.process != null) {
-      this.process.destroy();
-      this.process = null;
-    }
-    if (this.processOutReader != null && this.processOutReader.isRunning()) {
-      this.processOutReader.stop();
-    }
-    if (this.processErrReader != null && this.processErrReader.isRunning()) {
-      this.processErrReader.stop();
-    }
-  }
-
-  /**
-   * Override as needed.
-   */
-  protected List<String> getJvmArguments() {
-    final List<String> jvmArguments = new ArrayList<String>();
-    jvmArguments.add("-D" + DistributionConfig.GEMFIRE_PREFIX + "log-level=config");
-    return jvmArguments;
-  }
-
-  /**
-   * Remove final if a test needs to override.
-   */
-  protected AbstractLauncher.Status getExpectedStopStatusForNotRunning() {
-    return AbstractLauncher.Status.NOT_RESPONDING;
-  }
-
-  protected void waitForServerToStart() throws Exception {
-    assertEventuallyTrue("waiting for local Server to start: " + launcher.status(),
-        new Callable<Boolean>() {
-          @Override
-          public Boolean call() throws Exception {
-            try {
-              assertNotNull(process);
-              try {
-                final int value = process.exitValue();
-                fail("Process has died with exit value " + value
-                    + " while waiting for it to start.");
-              } catch (IllegalThreadStateException e) {
-                // expected
-              }
-              final ServerLauncher.ServerState serverState = launcher.status();
-              assertNotNull(serverState);
-              logger.info("serverState: " + serverState);
-              return AbstractLauncher.Status.ONLINE.equals(serverState.getStatus());
-            } catch (RuntimeException e) {
-              logger.error(e, e);
-              return false;
-            }
-          }
-        }, TIMEOUT_MILLISECONDS, INTERVAL_MILLISECONDS);
-  }
-
-}

http://git-wip-us.apache.org/repos/asf/geode/blob/894f3ee7/geode-core/src/test/java/org/apache/geode/distributed/LauncherIntegrationTestCase.java
----------------------------------------------------------------------
diff --git a/geode-core/src/test/java/org/apache/geode/distributed/LauncherIntegrationTestCase.java b/geode-core/src/test/java/org/apache/geode/distributed/LauncherIntegrationTestCase.java
new file mode 100755
index 0000000..409a96d
--- /dev/null
+++ b/geode-core/src/test/java/org/apache/geode/distributed/LauncherIntegrationTestCase.java
@@ -0,0 +1,314 @@
+/*
+ * 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 java.util.concurrent.TimeUnit.MINUTES;
+import static org.apache.geode.distributed.ConfigurationProperties.MCAST_PORT;
+import static org.apache.geode.internal.AvailablePort.SOCKET;
+import static org.apache.geode.internal.AvailablePort.isPortAvailable;
+import static org.apache.geode.internal.process.ProcessUtils.identifyPid;
+import static org.apache.geode.internal.process.ProcessUtils.isProcessAlive;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.junit.Assert.assertTrue;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileReader;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.UncheckedIOException;
+import java.lang.management.ManagementFactory;
+import java.net.ServerSocket;
+import java.util.List;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+import org.apache.commons.lang.StringUtils;
+import org.awaitility.Awaitility;
+import org.awaitility.core.ConditionFactory;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.contrib.java.lang.system.RestoreSystemProperties;
+import org.junit.rules.TemporaryFolder;
+import org.junit.rules.TestName;
+
+import org.apache.geode.distributed.internal.DistributionConfig;
+import org.apache.geode.distributed.internal.InternalDistributedSystem;
+import org.apache.geode.internal.net.SocketCreatorFactory;
+import org.apache.geode.internal.process.ProcessStreamReader.InputListener;
+import org.apache.geode.internal.process.ProcessType;
+import org.apache.geode.internal.process.lang.AvailablePid;
+import org.apache.geode.test.dunit.IgnoredException;
+
+/**
+ * Abstract base class for integration tests of both {@link LocatorLauncher} and
+ * {@link ServerLauncher}.
+ *
+ * @since GemFire 8.0
+ */
+public abstract class LauncherIntegrationTestCase {
+
+  private static final int PREFERRED_FAKE_PID = 42;
+
+  private static final String EXPECTED_EXCEPTION_MBEAN_NOT_REGISTERED =
+      "MBean Not Registered In GemFire Domain";
+
+  protected volatile int localPid;
+  protected volatile int fakePid;
+  private volatile ServerSocket socket;
+  private IgnoredException ignoredException;
+
+  @Rule
+  public RestoreSystemProperties restoreSystemProperties = new RestoreSystemProperties();
+
+  @Rule
+  public TemporaryFolder temporaryFolder = new TemporaryFolder();
+
+  @Rule
+  public TestName testName = new TestName();
+
+  @Before
+  public void setUpAbstractLauncherIntegrationTestCase() throws Exception {
+    System.setProperty(DistributionConfig.GEMFIRE_PREFIX + MCAST_PORT, Integer.toString(0));
+    ignoredException =
+        IgnoredException.addIgnoredException(EXPECTED_EXCEPTION_MBEAN_NOT_REGISTERED);
+    localPid = identifyPid();
+    fakePid = new AvailablePid().findAvailablePid(PREFERRED_FAKE_PID);
+  }
+
+  @After
+  public void tearDownAbstractLauncherIntegrationTestCase() throws Exception {
+    ignoredException.remove();
+    if (socket != null) {
+      socket.close();
+    }
+  }
+
+  protected abstract ProcessType getProcessType();
+
+  protected void assertDeletionOf(final File file) {
+    await().until(() -> assertThat(file).doesNotExist());
+  }
+
+  protected void assertThatServerPortIsFree(final int serverPort) {
+    assertThatPortIsFree(serverPort);
+  }
+
+  protected void assertThatServerPortIsInUse(final int serverPort) {
+    assertThatPortIsInUse(serverPort);
+  }
+
+  protected void assertThatServerPortIsInUseBySocket(final int serverPort) {
+    assertThatPortIsInUseBySocket(serverPort);
+  }
+
+  protected File givenControlFile(final String name) {
+    try {
+      File file = new File(getWorkingDirectory(), name);
+      assertThat(file.createNewFile()).isTrue();
+      assertThat(file).exists();
+      return file;
+    } catch (IOException e) {
+      throw new UncheckedIOException(e);
+    }
+  }
+
+  protected File givenEmptyPidFile() {
+    return givenPidFile(null);
+  }
+
+  protected void givenEmptyWorkingDirectory() {
+    assertThat(getWorkingDirectory().listFiles()).hasSize(0);
+  }
+
+  protected void givenLocatorPortInUse(final int locatorPort) {
+    givenPortInUse(locatorPort);
+  }
+
+  protected File givenPidFile(final Object content) {
+    try {
+      File file = new File(getWorkingDirectory(), getProcessType().getPidFileName());
+      FileWriter writer = new FileWriter(file);
+      writer.write(String.valueOf(content));
+      writer.write("\n");
+      writer.flush();
+      writer.close();
+      assertTrue(file.exists());
+      return file;
+    } catch (IOException e) {
+      throw new UncheckedIOException(e);
+    }
+  }
+
+  protected void givenServerPortIsFree(final int serverPort) {
+    assertThatPortIsFree(serverPort);
+  }
+
+  protected void givenServerPortInUse(final int serverPort) {
+    givenPortInUse(serverPort);
+  }
+
+  protected ConditionFactory await() {
+    return Awaitility.await().atMost(2, MINUTES);
+  }
+
+  protected InputListener createExpectedListener(final String name, final String expected,
+      final AtomicBoolean atomic) {
+    return new InputListener() {
+      @Override
+      public void notifyInputLine(String line) {
+        if (line.contains(expected)) {
+          atomic.set(true);
+        }
+      }
+
+      @Override
+      public String toString() {
+        return name;
+      }
+    };
+  }
+
+  protected void disconnectFromDS() {
+    InternalDistributedSystem ids = InternalDistributedSystem.getConnectedInstance();
+    if (ids != null) {
+      ids.disconnect();
+    }
+  }
+
+  public String getClassPath() {
+    // alternative: ManagementFactory.getRuntimeMXBean().getClassPath()
+    return System.getProperty("java.class.path");
+  }
+
+  public String getJavaPath() {
+    try {
+      return new File(new File(System.getProperty("java.home"), "bin"), "java").getCanonicalPath();
+    } catch (IOException e) {
+      throw new UncheckedIOException(e);
+    }
+  }
+
+  protected List<String> getJvmArguments() {
+    return ManagementFactory.getRuntimeMXBean().getInputArguments();
+  }
+
+  protected int getLocatorPid() {
+    return readPidFileWithValidation();
+  }
+
+  protected File getLogFile() {
+    return new File(getWorkingDirectory(), getUniqueName() + ".log");
+  }
+
+  protected String getLogFilePath() {
+    try {
+      return getLogFile().getCanonicalPath();
+    } catch (IOException e) {
+      throw new UncheckedIOException(e);
+    }
+  }
+
+  protected File getPidFile() {
+    return new File(getWorkingDirectory(), getProcessType().getPidFileName());
+  }
+
+  protected String getUniqueName() {
+    return getClass().getSimpleName() + "_" + testName.getMethodName();
+  }
+
+  protected int getServerPid() {
+    return readPidFileWithValidation();
+  }
+
+  protected String getStatusFileName() {
+    return getProcessType().getStatusFileName();
+  }
+
+  protected String getStatusRequestFileName() {
+    return getProcessType().getStatusRequestFileName();
+  }
+
+  protected String getStopRequestFileName() {
+    return getProcessType().getStopRequestFileName();
+  }
+
+  protected File getWorkingDirectory() {
+    return temporaryFolder.getRoot();
+  }
+
+  protected String getWorkingDirectoryPath() {
+    try {
+      return getWorkingDirectory().getCanonicalPath();
+    } catch (IOException e) {
+      throw new UncheckedIOException(e);
+    }
+  }
+
+  protected int readPidFile() {
+    return readPidFile(getPidFile());
+  }
+
+  private void assertThatPortIsFree(final int port) {
+    assertThat(isPortAvailable(port, SOCKET)).isTrue();
+  }
+
+  private void assertThatPortIsInUse(final int port) {
+    assertThat(isPortAvailable(port, SOCKET)).isFalse();
+  }
+
+  private void assertThatPortIsInUseBySocket(final int port) {
+    assertThat(socket.isBound()).isTrue();
+    assertThat(socket.isClosed()).isFalse();
+    assertThat(socket.getLocalPort()).isEqualTo(port);
+    assertThatServerPortIsInUse(port);
+  }
+
+  private void delete(final File file) {
+    assertThat(file.delete()).isTrue();
+  }
+
+  private void givenPortInUse(final int port) {
+    try {
+      socket = SocketCreatorFactory
+          .createNonDefaultInstance(false, false, null, null, System.getProperties())
+          .createServerSocket(port, 50, null, -1);
+      assertThat(socket.isBound()).isTrue();
+      assertThat(socket.isClosed()).isFalse();
+      assertThat(isPortAvailable(port, SOCKET)).isFalse();
+    } catch (IOException e) {
+      throw new UncheckedIOException(e);
+    }
+  }
+
+  private int readPidFile(final File pidFile) {
+    try {
+      assertTrue(pidFile.exists());
+      try (BufferedReader reader = new BufferedReader(new FileReader(pidFile))) {
+        return Integer.parseInt(StringUtils.trim(reader.readLine()));
+      }
+    } catch (IOException e) {
+      throw new UncheckedIOException(e);
+    }
+  }
+
+  private int readPidFileWithValidation() {
+    int pid = readPidFile(getPidFile());
+    assertThat(pid).isGreaterThan(0);
+    assertThat(isProcessAlive(pid)).isTrue();
+    return pid;
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/geode/blob/894f3ee7/geode-core/src/test/java/org/apache/geode/distributed/LauncherMemberMXBeanIntegrationTest.java
----------------------------------------------------------------------
diff --git a/geode-core/src/test/java/org/apache/geode/distributed/LauncherMemberMXBeanIntegrationTest.java b/geode-core/src/test/java/org/apache/geode/distributed/LauncherMemberMXBeanIntegrationTest.java
index 7b6cd7f..087f13b 100755
--- a/geode-core/src/test/java/org/apache/geode/distributed/LauncherMemberMXBeanIntegrationTest.java
+++ b/geode-core/src/test/java/org/apache/geode/distributed/LauncherMemberMXBeanIntegrationTest.java
@@ -14,136 +14,126 @@
  */
 package org.apache.geode.distributed;
 
-import org.apache.geode.cache.CacheFactory;
-import org.apache.geode.distributed.internal.InternalDistributedSystem;
-import org.apache.geode.internal.process.ProcessUtils;
-import org.apache.geode.management.MemberMXBean;
-import org.apache.geode.test.junit.categories.IntegrationTest;
+import static java.lang.management.ManagementFactory.getPlatformMBeanServer;
+import static java.util.concurrent.TimeUnit.MINUTES;
+import static javax.management.MBeanServerInvocationHandler.newProxyInstance;
+import static org.apache.geode.distributed.ConfigurationProperties.LOCATORS;
+import static org.apache.geode.distributed.ConfigurationProperties.MCAST_PORT;
+import static org.assertj.core.api.Assertions.assertThat;
+
+import java.util.Properties;
+import java.util.Set;
+
+import javax.management.MBeanServer;
+import javax.management.ObjectName;
+import javax.management.Query;
+import javax.management.QueryExp;
+
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.experimental.categories.Category;
 
-import javax.management.*;
-import java.lang.management.ManagementFactory;
-import java.util.Properties;
-import java.util.Set;
-import java.util.concurrent.Callable;
-
-import static org.apache.geode.distributed.ConfigurationProperties.LOCATORS;
-import static org.apache.geode.distributed.ConfigurationProperties.MCAST_PORT;
-import static org.junit.Assert.*;
+import org.apache.geode.cache.CacheFactory;
+import org.apache.geode.internal.process.ControllableProcess;
+import org.apache.geode.internal.process.ProcessType;
+import org.apache.geode.management.MemberMXBean;
+import org.apache.geode.test.junit.categories.IntegrationTest;
 
 /**
- * Tests querying of MemberMXBean which is used by MBeanProcessController to control GemFire
- * ControllableProcesses.
+ * Integration tests for querying of {@link MemberMXBean} as used in MBeanProcessController to
+ * manage a {@link ControllableProcess}.
+ *
+ * <p>
+ * This test is an experiment in using given/when/then custom methods for better BDD readability.
  * 
  * @since GemFire 8.0
  */
 @Category(IntegrationTest.class)
-public class LauncherMemberMXBeanIntegrationTest extends AbstractLauncherIntegrationTestCase {
-
-  @Before
-  public final void setUpLauncherMemberMXBeanIntegrationTest() throws Exception {}
+public class LauncherMemberMXBeanIntegrationTest extends LauncherIntegrationTestCase {
 
-  @After
-  public final void tearDownLauncherMemberMXBeanIntegrationTest() throws Exception {
-    InternalDistributedSystem ids = InternalDistributedSystem.getConnectedInstance();
-    if (ids != null) {
-      ids.disconnect();
-    }
-  }
+  private ObjectName pattern;
+  private QueryExp constraint;
+  private Set<ObjectName> mbeanNames;
 
-  @Test
-  public void testQueryForMemberMXBean() throws Exception {
-    final Properties props = new Properties();
+  @Before
+  public void setUp() throws Exception {
+    Properties props = new Properties();
     props.setProperty(MCAST_PORT, "0");
     props.setProperty(LOCATORS, "");
     props.setProperty("name", getUniqueName());
     new CacheFactory(props).create();
 
-    final MBeanServer mbeanServer = ManagementFactory.getPlatformMBeanServer();
-    final ObjectName pattern = ObjectName.getInstance("GemFire:type=Member,*");
+    pattern = ObjectName.getInstance("GemFire:type=Member,*");
+    waitForMemberMXBean(getPlatformMBeanServer(), pattern);
+  }
 
-    waitForMemberMXBean(mbeanServer, pattern);
+  @After
+  public void tearDown() throws Exception {
+    disconnectFromDS();
+  }
 
-    final Set<ObjectName> mbeanNames = mbeanServer.queryNames(pattern, null);
-    assertFalse(mbeanNames.isEmpty());
-    assertEquals("mbeanNames=" + mbeanNames, 1, mbeanNames.size());
+  @Test
+  public void queryWithNullFindsMemberMXBean() throws Exception {
+    givenConstraint(null);
 
-    final ObjectName objectName = mbeanNames.iterator().next();
-    final MemberMXBean mbean = MBeanServerInvocationHandler.newProxyInstance(mbeanServer,
-        objectName, MemberMXBean.class, false);
+    whenQuerying(getPlatformMBeanServer());
 
-    assertNotNull(mbean);
-    assertEquals(ProcessUtils.identifyPid(), mbean.getProcessId());
-    assertEquals(getUniqueName(), mbean.getName());
-    assertEquals(getUniqueName(), mbean.getMember());
+    thenMemberMXBeanShouldBeFound().andShouldMatchCurrentMember();
   }
 
   @Test
-  public void testQueryForMemberMXBeanWithProcessId() throws Exception {
-    final Properties props = new Properties();
-    props.setProperty(MCAST_PORT, "0");
-    props.setProperty(LOCATORS, "");
-    props.setProperty("name", getUniqueName());
-    new CacheFactory(props).create();
+  public void queryWithProcessIdFindsMemberMXBean() throws Exception {
+    givenConstraint(Query.eq(Query.attr("ProcessId"), Query.value(localPid)));
 
-    final MBeanServer mbeanServer = ManagementFactory.getPlatformMBeanServer();
-    final ObjectName pattern = ObjectName.getInstance("GemFire:type=Member,*");
-    final QueryExp constraint =
-        Query.eq(Query.attr("ProcessId"), Query.value(ProcessUtils.identifyPid()));
+    whenQuerying(getPlatformMBeanServer());
 
-    waitForMemberMXBean(mbeanServer, pattern);
+    thenMemberMXBeanShouldBeFound().andShouldMatchCurrentMember();
+  }
 
-    final Set<ObjectName> mbeanNames = mbeanServer.queryNames(pattern, constraint);
-    assertFalse(mbeanNames.isEmpty());
-    assertEquals(1, mbeanNames.size());
+  @Test
+  public void queryWithMemberNameFindsMemberMXBean() throws Exception {
+    givenConstraint(Query.eq(Query.attr("Name"), Query.value(getUniqueName())));
 
-    final ObjectName objectName = mbeanNames.iterator().next();
-    final MemberMXBean mbean = MBeanServerInvocationHandler.newProxyInstance(mbeanServer,
-        objectName, MemberMXBean.class, false);
+    whenQuerying(getPlatformMBeanServer());
 
-    assertNotNull(mbean);
-    assertEquals(ProcessUtils.identifyPid(), mbean.getProcessId());
-    assertEquals(getUniqueName(), mbean.getName());
-    assertEquals(getUniqueName(), mbean.getMember());
+    thenMemberMXBeanShouldBeFound().andShouldMatchCurrentMember();
   }
 
-  @Test
-  public void testQueryForMemberMXBeanWithMemberName() throws Exception {
-    final Properties props = new Properties();
-    props.setProperty(MCAST_PORT, "0");
-    props.setProperty(LOCATORS, "");
-    props.setProperty("name", getUniqueName());
-    new CacheFactory(props).create();
+  private void givenConstraint(final QueryExp constraint) {
+    this.constraint = constraint;
+  }
 
-    final MBeanServer mbeanServer = ManagementFactory.getPlatformMBeanServer();
-    final ObjectName pattern = ObjectName.getInstance("GemFire:type=Member,*");
-    final QueryExp constraint = Query.eq(Query.attr("Name"), Query.value(getUniqueName()));
+  private void whenQuerying(final MBeanServer mbeanServer) {
+    mbeanNames = mbeanServer.queryNames(pattern, constraint);
+  }
+
+  private LauncherMemberMXBeanIntegrationTest thenMemberMXBeanShouldBeFound() {
+    assertThat(mbeanNames).hasSize(1);
 
-    waitForMemberMXBean(mbeanServer, pattern);
+    return this;
+  }
 
-    final Set<ObjectName> mbeanNames = mbeanServer.queryNames(pattern, constraint);
-    assertFalse(mbeanNames.isEmpty());
-    assertEquals(1, mbeanNames.size());
+  private LauncherMemberMXBeanIntegrationTest andShouldMatchCurrentMember() {
+    ObjectName objectName = mbeanNames.iterator().next();
+    MemberMXBean mbean =
+        newProxyInstance(getPlatformMBeanServer(), objectName, MemberMXBean.class, false);
 
-    final ObjectName objectName = mbeanNames.iterator().next();
-    final MemberMXBean mbean = MBeanServerInvocationHandler.newProxyInstance(mbeanServer,
-        objectName, MemberMXBean.class, false);
+    assertThat(mbean.getMember()).isEqualTo(getUniqueName());
+    assertThat(mbean.getName()).isEqualTo(getUniqueName());
+    assertThat(mbean.getProcessId()).isEqualTo(localPid);
+
+    return this;
+  }
 
-    assertNotNull(mbean);
-    assertEquals(getUniqueName(), mbean.getMember());
+  @Override
+  protected ProcessType getProcessType() {
+    throw new UnsupportedOperationException(
+        "getProcessType is not used by " + getClass().getSimpleName());
   }
 
-  private void waitForMemberMXBean(final MBeanServer mbeanServer, final ObjectName pattern)
-      throws Exception {
-    assertEventuallyTrue("waiting for MemberMXBean to be registered", new Callable<Boolean>() {
-      @Override
-      public Boolean call() throws Exception {
-        Set<ObjectName> mbeanNames = mbeanServer.queryNames(pattern, null);
-        return !mbeanNames.isEmpty();
-      }
-    }, WAIT_FOR_MBEAN_TIMEOUT, INTERVAL_MILLISECONDS);
+  private void waitForMemberMXBean(final MBeanServer mbeanServer, final ObjectName pattern) {
+    await().atMost(2, MINUTES)
+        .until(() -> assertThat(mbeanServer.queryNames(pattern, null)).isNotEmpty());
   }
 }

http://git-wip-us.apache.org/repos/asf/geode/blob/894f3ee7/geode-core/src/test/java/org/apache/geode/distributed/LocatorCommand.java
----------------------------------------------------------------------
diff --git a/geode-core/src/test/java/org/apache/geode/distributed/LocatorCommand.java b/geode-core/src/test/java/org/apache/geode/distributed/LocatorCommand.java
new file mode 100644
index 0000000..ef809af
--- /dev/null
+++ b/geode-core/src/test/java/org/apache/geode/distributed/LocatorCommand.java
@@ -0,0 +1,107 @@
+/*
+ * 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 java.util.ArrayList;
+import java.util.List;
+
+import org.apache.geode.distributed.LocatorLauncher.Command;
+
+public class LocatorCommand {
+
+  private String javaPath;
+  private List<String> jvmArguments = new ArrayList<>();
+  private String classPath;
+  private Command command;
+  private String name;
+  private boolean force;
+  private int port;
+
+  public LocatorCommand() {
+    // do nothing
+  }
+
+  public LocatorCommand(final UsesLocatorCommand user) {
+    this.javaPath = user.getJavaPath();
+    this.jvmArguments = user.getJvmArguments();
+    this.classPath = user.getClassPath();
+    this.name = user.getName();
+    this.command = Command.START;
+  }
+
+  public LocatorCommand withJavaPath(final String javaPath) {
+    this.javaPath = javaPath;
+    return this;
+  }
+
+  public LocatorCommand withJvmArguments(final List<String> jvmArguments) {
+    this.jvmArguments = jvmArguments;
+    return this;
+  }
+
+  public LocatorCommand addJvmArgument(final String arg) {
+    this.jvmArguments.add(arg);
+    return this;
+  }
+
+  public LocatorCommand withClassPath(final String classPath) {
+    this.classPath = classPath;
+    return this;
+  }
+
+  public LocatorCommand withCommand(final Command command) {
+    this.command = command;
+    return this;
+  }
+
+  public LocatorCommand withName(final String name) {
+    this.name = name;
+    return this;
+  }
+
+  public LocatorCommand force() {
+    return force(true);
+  }
+
+  public LocatorCommand force(final boolean value) {
+    this.force = value;
+    return this;
+  }
+
+  public LocatorCommand withPort(final int port) {
+    this.port = port;
+    return this;
+  }
+
+  public List<String> create() {
+    List<String> cmd = new ArrayList<>();
+    cmd.add(javaPath);
+    cmd.addAll(jvmArguments);
+    cmd.add("-cp");
+    cmd.add(classPath);
+    cmd.add(LocatorLauncher.class.getName());
+    cmd.add(command.getName());
+    cmd.add(name);
+    if (force) {
+      cmd.add("--force");
+    }
+    cmd.add("--redirect-output");
+    if (port > 0) {
+      cmd.add("--port=" + port);
+    }
+    return cmd;
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/geode/blob/894f3ee7/geode-core/src/test/java/org/apache/geode/distributed/LocatorLauncherBuilderTest.java
----------------------------------------------------------------------
diff --git a/geode-core/src/test/java/org/apache/geode/distributed/LocatorLauncherBuilderTest.java b/geode-core/src/test/java/org/apache/geode/distributed/LocatorLauncherBuilderTest.java
new file mode 100644
index 0000000..cc01e6c
--- /dev/null
+++ b/geode-core/src/test/java/org/apache/geode/distributed/LocatorLauncherBuilderTest.java
@@ -0,0 +1,507 @@
+/*
+ * 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.ConfigurationProperties.NAME;
+import static org.apache.geode.internal.DistributionLocator.DEFAULT_LOCATOR_PORT;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+
+import joptsimple.OptionException;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.contrib.java.lang.system.RestoreSystemProperties;
+import org.junit.experimental.categories.Category;
+
+import org.apache.geode.distributed.LocatorLauncher.Builder;
+import org.apache.geode.distributed.LocatorLauncher.Command;
+import org.apache.geode.distributed.internal.DistributionConfig;
+import org.apache.geode.test.junit.categories.UnitTest;
+
+/**
+ * Unit tests for {@link LocatorLauncher.Builder}. Extracted from {@link LocatorLauncherTest}.
+ */
+@Category(UnitTest.class)
+public class LocatorLauncherBuilderTest {
+
+  private InetAddress localHost;
+
+  @Rule
+  public final RestoreSystemProperties restoreSystemProperties = new RestoreSystemProperties();
+
+  @Before
+  public void setUp() throws Exception {
+    localHost = InetAddress.getLocalHost();
+  }
+
+  @Test
+  public void defaultCommandIsUnspecified() throws Exception {
+    assertThat(Builder.DEFAULT_COMMAND).isEqualTo(Command.UNSPECIFIED);
+  }
+
+  @Test
+  public void getCommandReturnsUnspecifiedByDefault() throws Exception {
+    assertThat(new Builder().getCommand()).isEqualTo(Builder.DEFAULT_COMMAND);
+  }
+
+  @Test
+  public void getForceReturnsFalseByDefault() {
+    assertThat(new Builder().getForce()).isFalse();
+  }
+
+  @Test
+  public void getBindAddressReturnsNullByDefault() throws Exception {
+    Builder builder = new Builder();
+
+    assertThat(builder.getBindAddress()).isNull();
+  }
+
+  @Test
+  public void getHostnameForClientsReturnsNullByDefault() throws Exception {
+    assertThat(new Builder().getHostnameForClients()).isNull();
+  }
+
+  @Test
+  public void getMemberNameReturnsNullByDefault() throws Exception {
+    assertThat(new Builder().getMemberName()).isNull();
+  }
+
+  @Test
+  public void getPidReturnsNullByDefault() throws Exception {
+    assertThat(new Builder().getPid()).isNull();
+  }
+
+  @Test
+  public void getPortReturnsDefaultLocatorPortByDefault() throws Exception {
+    assertThat(new Builder().getPort()).isEqualTo(Integer.valueOf(DEFAULT_LOCATOR_PORT));
+  }
+
+  @Test
+  public void setCommandReturnsBuilderInstance() throws Exception {
+    Builder builder = new Builder();
+
+    assertThat(builder.setCommand(Command.STATUS)).isSameAs(builder);
+  }
+
+  @Test
+  public void setForceReturnsBuilderInstance() throws Exception {
+    Builder builder = new Builder();
+
+    assertThat(builder.setForce(true)).isSameAs(builder);
+  }
+
+  @Test
+  public void setHostNameForClientsReturnsBuilderInstance() throws Exception {
+    Builder builder = new Builder();
+
+    assertThat(builder.setHostnameForClients("Pegasus")).isSameAs(builder);
+  }
+
+  @Test
+  public void setMemberNameReturnsBuilderInstance() throws Exception {
+    Builder builder = new Builder();
+
+    assertThat(builder.setMemberName("serverOne")).isSameAs(builder);
+  }
+
+  @Test
+  public void setBindAddressReturnsBuilderInstance() throws Exception {
+    Builder builder = new Builder();
+
+    assertThat(builder.setBindAddress(null)).isSameAs(builder);
+  }
+
+  @Test
+  public void setPortReturnsBuilderInstance() throws Exception {
+    Builder builder = new Builder();
+
+    assertThat(builder.setPort(null)).isSameAs(builder);
+  }
+
+  @Test
+  public void setCommandWithNullResultsInDefaultCommand() throws Exception {
+    Builder builder = new Builder();
+
+    new Builder().setCommand(null);
+
+    assertThat(builder.getCommand()).isEqualTo(Builder.DEFAULT_COMMAND);
+  }
+
+  @Test
+  public void setCommandToStatusResultsInStatus() throws Exception {
+    Builder builder = new Builder();
+
+    builder.setCommand(Command.STATUS);
+
+    assertThat(builder.getCommand()).isEqualTo(Command.STATUS);
+  }
+
+  @Test
+  public void setBindAddressToNullResultsInNull() throws Exception {
+    Builder builder = new Builder();
+
+    builder.setBindAddress(null);
+
+    assertThat(builder.getBindAddress()).isNull();
+  }
+
+  @Test
+  public void setBindAddressToEmptyStringResultsInNull() throws Exception {
+    Builder builder = new Builder();
+
+    builder.setBindAddress("");
+
+    assertThat(builder.getBindAddress()).isNull();
+  }
+
+  @Test
+  public void setBindAddressToBlankStringResultsInNull() throws Exception {
+    Builder builder = new Builder();
+
+    builder.setBindAddress("  ");
+
+    assertThat(builder.getBindAddress()).isNull();
+  }
+
+  @Test
+  public void setBindAddressToCanonicalLocalHostUsesValue() throws Exception {
+    Builder builder = new Builder().setBindAddress(InetAddress.getLocalHost().getHostName());
+
+    assertThat(builder.getBindAddress()).isEqualTo(localHost);
+  }
+
+  @Test
+  public void setBindAddressToLocalHostNameUsesValue() throws Exception {
+    String host = InetAddress.getLocalHost().getHostName();
+
+    Builder builder = new Builder().setBindAddress(host);
+
+    assertThat(builder.getBindAddress()).isEqualTo(localHost);
+  }
+
+  @Test
+  public void setBindAddressToUnknownHostThrowsIllegalArgumentException() {
+    assertThatThrownBy(() -> new Builder().setBindAddress("badhostname.badcompany.bad"))
+        .isInstanceOf(IllegalArgumentException.class)
+        .hasCauseInstanceOf(UnknownHostException.class);
+  }
+
+  @Test
+  public void setBindAddressToNonLocalHostThrowsIllegalArgumentException() {
+    assertThatThrownBy(() -> new Builder().setBindAddress("yahoo.com"))
+        .isInstanceOf(IllegalArgumentException.class);
+  }
+
+  @Test
+  public void setForceToTrueUsesValue() throws Exception {
+    ServerLauncher.Builder builder = new ServerLauncher.Builder();
+
+    builder.setForce(true);
+
+    assertThat(builder.getForce()).isTrue();
+  }
+
+  @Test
+  public void setHostnameForClientsToStringUsesValue() throws Exception {
+    Builder builder = new Builder();
+
+    builder.setHostnameForClients("Pegasus");
+
+    assertThat(builder.getHostnameForClients()).isEqualTo("Pegasus");
+  }
+
+  @Test
+  public void setHostnameForClientsToBlankStringThrowsIllegalArgumentException() {
+    assertThatThrownBy(() -> new Builder().setHostnameForClients(" "))
+        .isInstanceOf(IllegalArgumentException.class);
+  }
+
+  @Test
+  public void setHostnameForClientsToEmptyStringThrowsIllegalArgumentException() {
+    assertThatThrownBy(() -> new Builder().setHostnameForClients(""))
+        .isInstanceOf(IllegalArgumentException.class);
+  }
+
+  @Test
+
+  public void setHostnameForClientsToNullThrowsIllegalArgumentException() {
+    assertThatThrownBy(() -> new Builder().setHostnameForClients(null))
+        .isInstanceOf(IllegalArgumentException.class);
+  }
+
+  @Test
+  public void setMemberNameToStringUsesValue() throws Exception {
+    Builder builder = new Builder();
+
+    builder.setMemberName("locatorOne");
+
+    assertThat(builder.getMemberName()).isEqualTo("locatorOne");
+  }
+
+  @Test
+  public void setMemberNameWithBlankStringThrowsIllegalArgumentException() {
+    assertThatThrownBy(() -> new Builder().setMemberName("  "))
+        .isInstanceOf(IllegalArgumentException.class);
+  }
+
+  @Test
+  public void setMemberNameWithEmptyStringThrowsIllegalArgumentException() {
+    assertThatThrownBy(() -> new Builder().setMemberName(""))
+        .isInstanceOf(IllegalArgumentException.class);
+  }
+
+  @Test
+  public void setMemberNameWithNullStringThrowsIllegalArgumentException() {
+    assertThatThrownBy(() -> new Builder().setMemberName(null))
+        .isInstanceOf(IllegalArgumentException.class);
+  }
+
+  @Test
+  public void setPidToZeroOrGreaterUsesValue() throws Exception {
+    Builder builder = new Builder();
+
+    builder.setPid(0);
+    assertThat(builder.getPid().intValue()).isEqualTo(0);
+
+    builder.setPid(1);
+    assertThat(builder.getPid().intValue()).isEqualTo(1);
+
+    builder.setPid(1024);
+    assertThat(builder.getPid().intValue()).isEqualTo(1024);
+
+    builder.setPid(12345);
+    assertThat(builder.getPid().intValue()).isEqualTo(12345);
+  }
+
+  @Test
+  public void setPidToNullResultsInNull() throws Exception {
+    Builder builder = new Builder();
+
+    builder.setPid(null);
+
+    assertThat(builder.getPid()).isNull();
+  }
+
+  @Test
+  public void setPidToNegativeValueThrowsIllegalArgumentException() {
+    assertThatThrownBy(() -> new Builder().setPid(-1)).isInstanceOf(IllegalArgumentException.class);
+  }
+
+  @Test
+  public void setPortToNullUsesDefaultLocatorPort() throws Exception {
+    Builder builder = new Builder();
+
+    assertThat(builder.setPort(null).getPort()).isEqualTo(Integer.valueOf(DEFAULT_LOCATOR_PORT));
+  }
+
+  @Test
+  public void setPortToZeroOrGreaterUsesValue() throws Exception {
+    Builder builder = new Builder();
+
+    builder.setPort(0);
+    assertThat(builder.getPort().intValue()).isEqualTo(0);
+
+    builder.setPort(1);
+    assertThat(builder.getPort().intValue()).isEqualTo(1);
+
+    builder.setPort(80);
+    assertThat(builder.getPort().intValue()).isEqualTo(80);
+
+    builder.setPort(1024);
+    assertThat(builder.getPort().intValue()).isEqualTo(1024);
+
+    builder.setPort(65535);
+    assertThat(builder.getPort().intValue()).isEqualTo(65535);
+  }
+
+  @Test
+  public void setPortAboveMaxValueThrowsIllegalArgumentException() throws Exception {
+    assertThatThrownBy(() -> new Builder().setPort(65536))
+        .isInstanceOf(IllegalArgumentException.class);
+  }
+
+  @Test
+  public void setPortToNegativeValueThrowsIllegalArgumentException() {
+    assertThatThrownBy(() -> new Builder().setPort(-1))
+        .isInstanceOf(IllegalArgumentException.class);
+  }
+
+  @Test
+  public void parseArgumentsWithForceSetsForceToTrue() throws Exception {
+    Builder builder = new Builder();
+
+    builder.parseArguments("start", "--force");
+
+    assertThat(builder.getForce()).isTrue();
+  }
+
+  @Test
+  public void parseArgumentsWithNonNumericPortThrowsIllegalArgumentException() {
+    assertThatThrownBy(
+        () -> new Builder().parseArguments("start", "locator1", "--port", "oneTwoThree"))
+            .isInstanceOf(IllegalArgumentException.class).hasCauseInstanceOf(OptionException.class);
+  }
+
+  @Test
+  public void parseCommandWithNullStringArrayResultsInDefaultCommand() throws Exception {
+    Builder builder = new Builder();
+
+    builder.parseCommand((String[]) null);
+
+    assertThat(builder.getCommand()).isEqualTo(Builder.DEFAULT_COMMAND);
+  }
+
+  @Test
+  public void parseCommandWithEmptyStringArrayResultsInDefaultCommand() throws Exception {
+    Builder builder = new Builder();
+
+    builder.parseCommand(); // empty String array
+
+    assertThat(builder.getCommand()).isEqualTo(Builder.DEFAULT_COMMAND);
+  }
+
+  @Test
+  public void parseCommandWithStartResultsInStartCommand() throws Exception {
+    Builder builder = new Builder();
+
+    builder.parseCommand(Command.START.getName());
+
+    assertThat(builder.getCommand()).isEqualTo(Command.START);
+  }
+
+  @Test
+  public void parseCommandWithStatusResultsInStatusCommand() throws Exception {
+    Builder builder = new Builder();
+
+    builder.parseCommand("Status");
+
+    assertThat(builder.getCommand()).isEqualTo(Command.STATUS);
+  }
+
+  @Test
+  public void parseCommandWithMixedCaseResultsInCorrectCase() throws Exception {
+    Builder builder = new Builder();
+
+    builder.parseCommand("sToP");
+
+    assertThat(builder.getCommand()).isEqualTo(Command.STOP);
+  }
+
+  @Test
+  public void parseCommandWithTwoCommandsWithSwitchesUsesFirstCommand() throws Exception {
+    Builder builder = new Builder();
+
+    builder.parseCommand("--opt", "START", "-o", Command.STATUS.getName());
+
+    assertThat(builder.getCommand()).isEqualTo(Command.START);
+  }
+
+  @Test
+  public void parseCommandWithTwoCommandsWithoutSwitchesUsesFirstCommand() throws Exception {
+    Builder builder = new Builder();
+
+    builder.parseCommand("START", Command.STATUS.getName());
+
+    assertThat(builder.getCommand()).isEqualTo(Command.START);
+  }
+
+  @Test
+  public void parseCommandWithBadInputResultsInDefaultCommand() throws Exception {
+    Builder builder = new Builder();
+
+    builder.parseCommand("badCommandName", "--start", "stat");
+
+    assertThat(builder.getCommand()).isEqualTo(Builder.DEFAULT_COMMAND);
+  }
+
+  @Test
+  public void parseMemberNameWithNullStringArrayResultsInNull() throws Exception {
+    Builder builder = new Builder();
+
+    builder.parseMemberName((String[]) null);
+
+    assertThat(builder.getMemberName()).isNull();
+  }
+
+  @Test
+  public void parseMemberNameWithEmptyStringArrayResultsInNull() throws Exception {
+    Builder builder = new Builder();
+
+    builder.parseMemberName(); // empty String array
+
+    assertThat(builder.getMemberName()).isNull();
+  }
+
+  @Test
+  public void parseMemberNameWithCommandAndOptionsResultsInNull() throws Exception {
+    Builder builder = new Builder();
+
+    builder.parseMemberName(Command.START.getName(), "--opt", "-o");
+
+    assertThat(builder.getMemberName()).isNull();
+  }
+
+  @Test
+  public void parseMemberNameWithStringUsesValue() throws Exception {
+    Builder builder = new Builder();
+
+    builder.parseMemberName("memberOne");
+
+    assertThat(builder.getMemberName()).isEqualTo("memberOne");
+  }
+
+
+  @Test
+  public void buildCreatesLocatorLauncherWithBuilderValues() throws Exception {
+    Builder builder = new Builder();
+
+    LocatorLauncher launcher = builder.setCommand(Command.START).setDebug(true)
+        .setHostnameForClients("beanstock.vmware.com").setMemberName("Beanstock").setPort(8192)
+        .build();
+
+    assertThat(launcher.getCommand()).isEqualTo(builder.getCommand());
+    assertThat(launcher.isDebugging()).isTrue();
+    assertThat(launcher.getHostnameForClients()).isEqualTo(builder.getHostnameForClients());
+    assertThat(launcher.getMemberName()).isEqualTo(builder.getMemberName());
+    assertThat(launcher.getPort()).isEqualTo(builder.getPort());
+    assertThat(launcher.getWorkingDirectory()).isEqualTo(builder.getWorkingDirectory());
+
+    assertThat(launcher.isHelping()).isFalse();
+    assertThat(launcher.isRunning()).isFalse();
+  }
+
+  @Test
+  public void buildUsesMemberNameSetInApiProperties() {
+    LocatorLauncher launcher =
+        new Builder().setCommand(LocatorLauncher.Command.START).set(NAME, "locatorABC").build();
+
+    assertThat(launcher.getMemberName()).isNull();
+    assertThat(launcher.getProperties().getProperty(NAME)).isEqualTo("locatorABC");
+  }
+
+  @Test
+  public void buildUsesMemberNameSetInSystemPropertiesOnStart() {
+    System.setProperty(DistributionConfig.GEMFIRE_PREFIX + NAME, "locatorXYZ");
+
+    LocatorLauncher launcher = new Builder().setCommand(LocatorLauncher.Command.START).build();
+
+    assertThat(launcher.getCommand()).isEqualTo(LocatorLauncher.Command.START);
+    assertThat(launcher.getMemberName()).isNull();
+  }
+}