You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@geode.apache.org by kirklund <gi...@git.apache.org> on 2017/08/09 18:52:27 UTC

[GitHub] geode pull request #699: GEODE-3413: overhaul launcher and process classes a...

GitHub user kirklund opened a pull request:

    https://github.com/apache/geode/pull/699

    GEODE-3413: overhaul launcher and process classes and tests

    This is primarily an overall of all ServerLauncher and LocatorLauncher
    tests and org.apache.geode.internal.process tests. The main classes in
    org.apachage.geode.internal.process package are also cleaned up.
    
    In addition, several bugs involving these classes and tests are fixed.
    
    Here is the complete list of tickets that are resolved in this overhaul:
    
    * GEODE-1229: LocatorLauncherRemoteJUnitTest.testStartOverwritesStalePidFile
    * GEODE-2791: LocatorLauncherAssemblyIntegrationTest.testLocatorStopsWhenJmxPortIsNonZero fails intermittently with AssertionError
    * GEODE-1308: CI failure: LocatorLauncherTest.testSetBindAddressToNonLocalHost
    * GEODE-1309: CI failure: ServerLauncherTest.testSetServerBindAddressToNonLocalHost
    * GEODE-3193: locator pid file is removed even if there was a problem while shutting down
    * GEODE-3413: Overhaul launcher tests and process tests
    * GEODE-3414: Cleanup org.apache.geode.internal.process package
    
    Note I moved all useful tests from LocatorLauncherAssemblyIntegrationTest
    into the other launcher tests in geode-core.


You can merge this pull request into a Git repository by running:

    $ git pull https://github.com/kirklund/geode GEODE-3183-3413-3414

Alternatively you can review and apply these changes as the patch at:

    https://github.com/apache/geode/pull/699.patch

To close this pull request, make a commit to your master/trunk branch
with (at least) the following in the commit message:

    This closes #699
    
----
commit 69cdd5cbc7423577b0a5fcde5f8da486437fa387
Author: Kirk Lund <kl...@apache.org>
Date:   2017-07-10T19:30:09Z

    GEODE-3413: overhaul launcher and process classes and tests
    
    This is primarily an overall of all ServerLauncher and LocatorLauncher
    tests and org.apache.geode.internal.process tests. The main classes in
    org.apachage.geode.internal.process package are also cleaned up.
    
    In addition, several bugs involving these classes and tests are fixed.
    
    Here is the complete list of tickets that are resolved in this overhaul:
    
    * GEODE-1229: LocatorLauncherRemoteJUnitTest.testStartOverwritesStalePidFile
    * GEODE-2791: LocatorLauncherAssemblyIntegrationTest.testLocatorStopsWhenJmxPortIsNonZero fails intermittently with AssertionError
    * GEODE-1308: CI failure: LocatorLauncherTest.testSetBindAddressToNonLocalHost
    * GEODE-1309: CI failure: ServerLauncherTest.testSetServerBindAddressToNonLocalHost
    * GEODE-3193: locator pid file is removed even if there was a problem while shutting down
    * GEODE-3413: Overhaul launcher tests and process tests
    * GEODE-3414: Cleanup org.apache.geode.internal.process package
    
    Note I moved all useful tests from LocatorLauncherAssemblyIntegrationTest
    into the other launcher tests in geode-core.

----


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] geode pull request #699: GEODE-3413: overhaul launcher and process classes a...

Posted by PurelyApplied <gi...@git.apache.org>.
Github user PurelyApplied commented on a diff in the pull request:

    https://github.com/apache/geode/pull/699#discussion_r132307061
  
    --- Diff: geode-core/src/main/java/org/apache/geode/distributed/AbstractLauncher.java ---
    @@ -157,7 +162,7 @@ protected static Properties loadGemFireProperties(final URL url) {
         if (url != null) {
           try {
             properties.load(new FileReader(new File(url.toURI())));
    -      } catch (Exception e) {
    +      } catch (Exception ignored) {
    --- End diff --
    
    Are we really ignoring the exception if we're doing something in response to it?
      Ditto lines 272, 438.


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] geode pull request #699: GEODE-3413: overhaul launcher and process classes a...

Posted by jaredjstewart <gi...@git.apache.org>.
Github user jaredjstewart commented on a diff in the pull request:

    https://github.com/apache/geode/pull/699#discussion_r132572256
  
    --- Diff: geode-core/src/main/java/org/apache/geode/internal/process/AttachProcessUtils.java ---
    @@ -14,21 +14,28 @@
      */
     package org.apache.geode.internal.process;
     
    -import org.apache.geode.internal.process.ProcessUtils.InternalProcessUtils;
    +import static org.apache.commons.lang.Validate.isTrue;
    +
     import com.sun.tools.attach.VirtualMachine;
     import com.sun.tools.attach.VirtualMachineDescriptor;
     
    +import org.apache.geode.internal.process.ProcessUtils.InternalProcessUtils;
    +
     /**
      * Implementation of the {@link ProcessUtils} SPI that uses the JDK Attach API.
      * 
      * @since GemFire 8.0
      */
     class AttachProcessUtils implements InternalProcessUtils {
     
    -  AttachProcessUtils() {}
    +  AttachProcessUtils() {
    --- End diff --
    
    Is there any reason to include this constructor at all?


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] geode pull request #699: GEODE-3413: overhaul launcher and process classes a...

Posted by kirklund <gi...@git.apache.org>.
Github user kirklund commented on a diff in the pull request:

    https://github.com/apache/geode/pull/699#discussion_r132542157
  
    --- Diff: geode-core/src/test/java/org/apache/geode/distributed/ServerLauncherRemoteIntegrationTestCase.java ---
    @@ -0,0 +1,270 @@
    +/*
    + * 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.LOG_LEVEL;
    +import static org.apache.geode.distributed.ConfigurationProperties.MCAST_PORT;
    +import static org.apache.geode.distributed.internal.DistributionConfig.GEMFIRE_PREFIX;
    +import static org.apache.geode.internal.cache.AbstractCacheServer.TEST_OVERRIDE_DEFAULT_PORT_PROPERTY;
    +import static org.apache.geode.internal.process.ProcessUtils.isProcessAlive;
    +import static org.assertj.core.api.Assertions.assertThat;
    +
    +import java.io.File;
    +import java.io.IOException;
    +import java.io.UncheckedIOException;
    +import java.net.BindException;
    +import java.util.ArrayList;
    +import java.util.List;
    +import java.util.concurrent.atomic.AtomicBoolean;
    +
    +import org.junit.After;
    +import org.junit.Before;
    +
    +import org.apache.geode.distributed.AbstractLauncher.Status;
    +import org.apache.geode.internal.process.ProcessStreamReader;
    +import org.apache.geode.internal.process.ProcessStreamReader.InputListener;
    +
    +/**
    + * Abstract base class for integration tests of {@link ServerLauncher} as an application main in a
    + * forked JVM.
    + *
    + * @since GemFire 8.0
    + */
    +public abstract class ServerLauncherRemoteIntegrationTestCase
    +    extends ServerLauncherIntegrationTestCase implements UsesServerCommand {
    +
    +  private final AtomicBoolean threwBindException = new AtomicBoolean();
    +
    +  protected volatile Process process;
    +  protected volatile ProcessStreamReader processOutReader;
    +  protected volatile ProcessStreamReader processErrReader;
    +
    +  private ServerCommand serverCommand;
    +
    +  @Before
    +  public void setUp() throws Exception {
    +    serverCommand = new ServerCommand(this);
    +  }
    +
    +  @After
    +  public 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
    +  public List<String> getJvmArguments() {
    +    List<String> jvmArguments = new ArrayList<>();
    +    jvmArguments.add("-D" + GEMFIRE_PREFIX + LOG_LEVEL + "=config");
    +    jvmArguments.add("-D" + GEMFIRE_PREFIX + MCAST_PORT + "=0");
    +    jvmArguments
    +        .add("-D" + TEST_OVERRIDE_DEFAULT_PORT_PROPERTY + "=" + String.valueOf(defaultServerPort));
    +    return jvmArguments;
    +  }
    +
    +  @Override
    +  public String getName() {
    +    return getUniqueName();
    +  }
    +
    +  @Override
    +  public boolean getDisableDefaultServer() {
    +    return false;
    +  }
    +
    +  protected void assertThatServerThrewBindException() {
    +    assertThat(threwBindException.get()).isTrue();
    +  }
    +
    +  protected void assertThatServerThrew(final Class<? extends Throwable> throwableClass) {
    +    assertThat(threwBindException.get()).isTrue();
    +  }
    +
    +  protected ServerLauncher startServer(final ServerCommand command) {
    +    return awaitStart(command);
    +  }
    +
    +  protected ServerLauncher awaitStart(final ServerCommand command,
    +      final ProcessStreamReader.InputListener outListener,
    +      final ProcessStreamReader.InputListener errListener) throws Exception {
    +    executeCommandWithReaders(command.create(), outListener, errListener);
    +    ServerLauncher launcher = awaitStart(getWorkingDirectory());
    +    assertThat(process.isAlive()).isTrue();
    +    return launcher;
    +  }
    +
    +  protected ServerLauncher awaitStart(final ServerCommand command) {
    +    try {
    +      executeCommandWithReaders(command);
    +      ServerLauncher launcher = awaitStart(getWorkingDirectory());
    +      assertThat(process.isAlive()).isTrue();
    +      return launcher;
    +    } catch (IOException e) {
    +      throw new UncheckedIOException(e);
    +    }
    +  }
    +
    +  protected ServerLauncher awaitStart(final File workingDirectory) {
    +    try {
    +      this.launcher = new ServerLauncher.Builder()
    +          .setWorkingDirectory(workingDirectory.getCanonicalPath()).build();
    +      ServerLauncher launcher = awaitStart(this.launcher);
    +      assertThat(process.isAlive()).isTrue();
    +      return launcher;
    +    } catch (IOException e) {
    +      throw new UncheckedIOException(e);
    +    }
    +  }
    +
    +  @Override
    +  protected ServerLauncher awaitStart(final ServerLauncher launcher) {
    +    await().until(() -> assertThat(launcher.status().getStatus()).isEqualTo(Status.ONLINE));
    +    assertThat(process.isAlive()).isTrue();
    +    return launcher;
    +  }
    +
    +  protected ServerLauncher awaitStart() {
    --- End diff --
    
    All unused methods deleted.


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] geode pull request #699: GEODE-3413: overhaul launcher and process classes a...

Posted by kirklund <gi...@git.apache.org>.
Github user kirklund commented on a diff in the pull request:

    https://github.com/apache/geode/pull/699#discussion_r132535229
  
    --- Diff: geode-core/src/main/java/org/apache/geode/distributed/AbstractLauncher.java ---
    @@ -157,7 +162,7 @@ protected static Properties loadGemFireProperties(final URL url) {
         if (url != null) {
           try {
             properties.load(new FileReader(new File(url.toURI())));
    -      } catch (Exception e) {
    +      } catch (Exception ignored) {
    --- End diff --
    
    Done.


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] geode pull request #699: GEODE-3413: overhaul launcher and process classes a...

Posted by kirklund <gi...@git.apache.org>.
Github user kirklund commented on a diff in the pull request:

    https://github.com/apache/geode/pull/699#discussion_r132542184
  
    --- Diff: geode-core/src/test/java/org/apache/geode/distributed/ServerLauncherRemoteIntegrationTestCase.java ---
    @@ -0,0 +1,270 @@
    +/*
    + * 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.LOG_LEVEL;
    +import static org.apache.geode.distributed.ConfigurationProperties.MCAST_PORT;
    +import static org.apache.geode.distributed.internal.DistributionConfig.GEMFIRE_PREFIX;
    +import static org.apache.geode.internal.cache.AbstractCacheServer.TEST_OVERRIDE_DEFAULT_PORT_PROPERTY;
    +import static org.apache.geode.internal.process.ProcessUtils.isProcessAlive;
    +import static org.assertj.core.api.Assertions.assertThat;
    +
    +import java.io.File;
    +import java.io.IOException;
    +import java.io.UncheckedIOException;
    +import java.net.BindException;
    +import java.util.ArrayList;
    +import java.util.List;
    +import java.util.concurrent.atomic.AtomicBoolean;
    +
    +import org.junit.After;
    +import org.junit.Before;
    +
    +import org.apache.geode.distributed.AbstractLauncher.Status;
    +import org.apache.geode.internal.process.ProcessStreamReader;
    +import org.apache.geode.internal.process.ProcessStreamReader.InputListener;
    +
    +/**
    + * Abstract base class for integration tests of {@link ServerLauncher} as an application main in a
    + * forked JVM.
    + *
    + * @since GemFire 8.0
    + */
    +public abstract class ServerLauncherRemoteIntegrationTestCase
    +    extends ServerLauncherIntegrationTestCase implements UsesServerCommand {
    +
    +  private final AtomicBoolean threwBindException = new AtomicBoolean();
    +
    +  protected volatile Process process;
    +  protected volatile ProcessStreamReader processOutReader;
    +  protected volatile ProcessStreamReader processErrReader;
    +
    +  private ServerCommand serverCommand;
    +
    +  @Before
    +  public void setUp() throws Exception {
    +    serverCommand = new ServerCommand(this);
    +  }
    +
    +  @After
    +  public 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
    +  public List<String> getJvmArguments() {
    +    List<String> jvmArguments = new ArrayList<>();
    +    jvmArguments.add("-D" + GEMFIRE_PREFIX + LOG_LEVEL + "=config");
    +    jvmArguments.add("-D" + GEMFIRE_PREFIX + MCAST_PORT + "=0");
    +    jvmArguments
    +        .add("-D" + TEST_OVERRIDE_DEFAULT_PORT_PROPERTY + "=" + String.valueOf(defaultServerPort));
    +    return jvmArguments;
    +  }
    +
    +  @Override
    +  public String getName() {
    +    return getUniqueName();
    +  }
    +
    +  @Override
    +  public boolean getDisableDefaultServer() {
    +    return false;
    +  }
    +
    +  protected void assertThatServerThrewBindException() {
    +    assertThat(threwBindException.get()).isTrue();
    +  }
    +
    +  protected void assertThatServerThrew(final Class<? extends Throwable> throwableClass) {
    +    assertThat(threwBindException.get()).isTrue();
    +  }
    +
    +  protected ServerLauncher startServer(final ServerCommand command) {
    +    return awaitStart(command);
    +  }
    +
    +  protected ServerLauncher awaitStart(final ServerCommand command,
    +      final ProcessStreamReader.InputListener outListener,
    +      final ProcessStreamReader.InputListener errListener) throws Exception {
    +    executeCommandWithReaders(command.create(), outListener, errListener);
    +    ServerLauncher launcher = awaitStart(getWorkingDirectory());
    +    assertThat(process.isAlive()).isTrue();
    +    return launcher;
    +  }
    +
    +  protected ServerLauncher awaitStart(final ServerCommand command) {
    +    try {
    +      executeCommandWithReaders(command);
    +      ServerLauncher launcher = awaitStart(getWorkingDirectory());
    +      assertThat(process.isAlive()).isTrue();
    +      return launcher;
    +    } catch (IOException e) {
    +      throw new UncheckedIOException(e);
    +    }
    +  }
    +
    +  protected ServerLauncher awaitStart(final File workingDirectory) {
    +    try {
    +      this.launcher = new ServerLauncher.Builder()
    +          .setWorkingDirectory(workingDirectory.getCanonicalPath()).build();
    +      ServerLauncher launcher = awaitStart(this.launcher);
    +      assertThat(process.isAlive()).isTrue();
    +      return launcher;
    +    } catch (IOException e) {
    +      throw new UncheckedIOException(e);
    +    }
    +  }
    +
    +  @Override
    +  protected ServerLauncher awaitStart(final ServerLauncher launcher) {
    +    await().until(() -> assertThat(launcher.status().getStatus()).isEqualTo(Status.ONLINE));
    +    assertThat(process.isAlive()).isTrue();
    +    return launcher;
    +  }
    +
    +  protected ServerLauncher awaitStart() {
    +    return awaitStart(this.launcher);
    +  }
    +
    +  protected void awaitStop() {
    +    await().until(() -> assertThat(this.process.isAlive()).isFalse());
    +  }
    +
    +  protected void assertStopOf(final Process process) {
    +    await().until(() -> assertThat(process.isAlive()).isFalse());
    +  }
    +
    +  protected Process getServerProcess() {
    +    return this.process;
    +  }
    +
    +  protected void startServerShouldFail(final ServerCommand command, final InputListener outListener,
    +      final InputListener errListener) throws IOException, InterruptedException {
    +    executeCommandWithReaders(command.create(), outListener, errListener);
    +    process.waitFor(2, MINUTES);
    +    assertThat(process.isAlive()).isFalse();
    +    assertThat(process.exitValue()).isEqualTo(1);
    +  }
    +
    +  protected void startServerShouldFail(final ServerCommand command)
    +      throws IOException, InterruptedException {
    +    startServerShouldFail(command, createBindExceptionListener("sysout", threwBindException),
    +        createBindExceptionListener("syserr", threwBindException));
    +  }
    +
    +  protected void startServerShouldFail() throws IOException, InterruptedException {
    +    startServerShouldFail(serverCommand);
    +  }
    +
    +  private InputListener createBindExceptionListener(final String name,
    +      final AtomicBoolean threwBindException) {
    +    return createExpectedListener(name, getUniqueName() + "#" + name, BindException.class.getName(),
    +        threwBindException);
    +  }
    +
    +  @Override
    +  protected ServerLauncher startServer() {
    +    return startServer(serverCommand);
    +  }
    +
    +  protected void assertThatProcessIsNotAlive() {
    +    assertThatProcessIsNotAlive(process);
    +  }
    +
    +  protected void assertThatProcessIsNotAlive(final Process process) {
    +    assertThat(process.isAlive()).isFalse();
    +  }
    +
    +  protected void assertProcessIsNotAlive() {
    --- End diff --
    
    All unused methods deleted.


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] geode pull request #699: GEODE-3413: overhaul launcher and process classes a...

Posted by pdxrunner <gi...@git.apache.org>.
Github user pdxrunner commented on a diff in the pull request:

    https://github.com/apache/geode/pull/699#discussion_r132497014
  
    --- Diff: geode-core/src/test/java/org/apache/geode/internal/process/NonBlockingProcessStreamReaderIntegrationTest.java ---
    @@ -0,0 +1,182 @@
    +/*
    + * 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.internal.process;
    +
    +import static org.apache.geode.internal.process.ProcessStreamReader.ReadingMode.NON_BLOCKING;
    +import static org.apache.geode.internal.process.ProcessUtils.isProcessAlive;
    +import static org.assertj.core.api.Assertions.assertThat;
    +
    +import org.junit.Before;
    +import org.junit.Test;
    +import org.junit.experimental.categories.Category;
    +
    +import org.apache.geode.internal.process.ProcessStreamReader.Builder;
    +import org.apache.geode.test.junit.categories.IntegrationTest;
    +
    +/**
    + * Functional integration tests for NonBlockingProcessStreamReader which was introduced to fix TRAC
    + * #51967.
    + *
    + * @see BlockingProcessStreamReaderIntegrationTest
    + * @see BlockingProcessStreamReaderWindowsTest
    + *
    + * @since GemFire 8.2
    + */
    +@Category(IntegrationTest.class)
    +public class NonBlockingProcessStreamReaderIntegrationTest
    +    extends BaseProcessStreamReaderIntegrationTest {
    +
    +  private StringBuffer stdoutBuffer;
    +  private StringBuffer stderrBuffer;
    +
    +  @Before
    +  public void before() {
    +    stdoutBuffer = new StringBuffer();
    +    stderrBuffer = new StringBuffer();
    +  }
    +
    +  /**
    +   * This test hangs on Windows if the implementation is blocking instead of non-blocking.
    +   */
    +  @Test
    +  public void canCloseStreamsWhileProcessIsAlive() throws Exception {
    +    // arrange
    +    process = new ProcessBuilder(createCommandLine(ProcessSleeps.class)).start();
    +    stdout = new Builder(process).inputStream(process.getInputStream()).readingMode(NON_BLOCKING)
    +        .build().start();
    +    stderr = new Builder(process).inputStream(process.getErrorStream()).readingMode(NON_BLOCKING)
    --- End diff --
    
    It looks like there may be an opportunity to extract a method from the common code from the beginning of each test. Yes, there are some variations on setting stdout and stderr, so maybe a couple methods to avoid duplicated code?


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] geode pull request #699: GEODE-3413: overhaul launcher and process classes a...

Posted by kirklund <gi...@git.apache.org>.
Github user kirklund commented on a diff in the pull request:

    https://github.com/apache/geode/pull/699#discussion_r132599897
  
    --- Diff: geode-core/src/main/java/org/apache/geode/internal/process/LocalProcessLauncher.java ---
    @@ -96,33 +117,55 @@ void close() {
        * @throws IOException if unable to create or write to the file
        */
       private void writePid(final boolean force) throws FileAlreadyExistsException, IOException {
    -    final boolean created = this.pidFile.createNewFile();
    -    if (!created && !force) {
    -      int otherPid = 0;
    -      try {
    -        otherPid = ProcessUtils.readPid(this.pidFile);
    -      } catch (IOException e) {
    -        // suppress
    -      } catch (NumberFormatException e) {
    -        // suppress
    -      }
    -      boolean ignorePidFile = false;
    -      if (otherPid != 0 && !ignoreIsPidAlive()) {
    -        ignorePidFile = !ProcessUtils.isProcessAlive(otherPid);
    -      }
    -      if (!ignorePidFile) {
    -        throw new FileAlreadyExistsException("Pid file already exists: " + this.pidFile + " for "
    -            + (otherPid > 0 ? "process " + otherPid : "unknown process"));
    +    if (this.pidFile.exists()) {
    +      if (!force) {
    +        checkOtherPid(readOtherPid());
           }
    +      this.pidFile.delete();
    +    }
    +
    +    assert !this.pidFile.exists();
    --- End diff --
    
    Did you like the use of Validate? I'm not sure how I feel about Validate after using it heavily in this package.
    
    Jianxia added the asserts when he fixed a bug in this method and I just left them in place. I think we could easily change them to Validate calls or remove them altogether.


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] geode pull request #699: GEODE-3413: overhaul launcher and process classes a...

Posted by jaredjstewart <gi...@git.apache.org>.
Github user jaredjstewart commented on a diff in the pull request:

    https://github.com/apache/geode/pull/699#discussion_r132571788
  
    --- Diff: geode-core/src/main/java/org/apache/geode/internal/config/ClusterConfigurationNotAvailableException.java ---
    @@ -0,0 +1,29 @@
    +/*
    + * 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.internal.config;
    +
    +/**
    + * Exception thrown during server startup when it requests the locators for shared configuration and
    + * does not receive it.
    + */
    +public class ClusterConfigurationNotAvailableException
    +    extends org.apache.geode.internal.process.ClusterConfigurationNotAvailableException {
    +
    +  private static final long serialVersionUID = 771319836094239284L;
    --- End diff --
    
    Since this is a new class and there is no need to worry about backwards compatibility with an autogenerated `serialVersionUID`, I think you can just use `0L`.


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] geode pull request #699: GEODE-3413: overhaul launcher and process classes a...

Posted by pdxrunner <gi...@git.apache.org>.
Github user pdxrunner commented on a diff in the pull request:

    https://github.com/apache/geode/pull/699#discussion_r132291477
  
    --- Diff: geode-core/src/test/java/org/apache/geode/distributed/AbstractLauncherTest.java ---
    @@ -14,253 +14,370 @@
      */
     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 isSetReturnsFalseIfPropertyHasRealValue() 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)).isTrue();
       }
     
       @Test
    -  public void testLoadGemFirePropertiesWithNullURL() {
    -    final Properties properties = AbstractLauncher.loadGemFireProperties(null);
    -    assertNotNull(properties);
    -    assertTrue(properties.isEmpty());
    +  public void isSetKeyIsCaseSensitive() throws Exception {
    +    Properties properties = new Properties();
    +
    +    properties.setProperty(NAME, "memberOne");
    +
    +    assertThat(AbstractLauncher.isSet(properties, "NaMe")).isFalse();
       }
     
       @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 loadGemFirePropertiesWithNullURLReturnsEmptyProperties() throws Exception {
    +    URL nullUrl = null;
    +
    +    Properties properties = AbstractLauncher.loadGemFireProperties(nullUrl);
    +
    +    assertThat(properties).isNotNull().isEmpty();
       }
     
       @Test
    -  public void testGetDistributedSystemProperties() {
    -    AbstractLauncher<?> launcher = createAbstractLauncher("memberOne", "1");
    +  public void loadGemFirePropertiesWithNonExistingURLReturnsEmptyProperties() throws Exception {
    +    URL nonExistingUrl = new URL("file:///path/to/non_existing/gemfire.properties");
    +
    +    Properties properties = AbstractLauncher.loadGemFireProperties(nonExistingUrl);
     
    -    assertNotNull(launcher);
    -    assertEquals("1", launcher.getMemberId());
    -    assertEquals("memberOne", launcher.getMemberName());
    +    assertThat(properties).isNotNull().isEmpty();
    +  }
     
    -    Properties distributedSystemProperties = launcher.getDistributedSystemProperties();
    +  @Test
    +  public void abstractLauncherHasMemberIdAndMemberName() throws Exception {
    --- End diff --
    
    I don't see the need for all the tests that exercise methods that are overridden in the embedded test class for AbstractLauncher. Any test that calls, for instance, 'launcher.getMemberId()' is only testing the test class, not the default implementation in the abstract class.


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] geode pull request #699: GEODE-3413: overhaul launcher and process classes a...

Posted by PurelyApplied <gi...@git.apache.org>.
Github user PurelyApplied commented on a diff in the pull request:

    https://github.com/apache/geode/pull/699#discussion_r132306579
  
    --- Diff: geode-core/src/main/java/org/apache/geode/internal/cache/ClusterConfigurationLoader.java ---
    @@ -31,7 +31,7 @@
     import org.apache.geode.internal.admin.remote.DistributionLocatorId;
     import org.apache.geode.internal.i18n.LocalizedStrings;
     import org.apache.geode.internal.logging.LogService;
    -import org.apache.geode.internal.process.ClusterConfigurationNotAvailableException;
    +import org.apache.geode.config.internal.ClusterConfigurationNotAvailableException;
    --- End diff --
    
    Classic Pat nitpick: don't forget to reorder / optimize your imports to go `statics`, `java`, `javax`, (other), `org.apache.geode`.
    
    This applies to the following files:
    ```
    geode-core/src/main/java/org/apache/geode/distributed/ServerLauncher.java
    geode-core/src/main/java/org/apache/geode/distributed/internal/InternalLocator.java
    geode-core/src/main/java/org/apache/geode/internal/cache/ClusterConfigurationLoader.java
    geode-core/src/main/java/org/apache/geode/internal/cache/GemFireCacheImpl.java
    geode-core/src/main/java/org/apache/geode/internal/process/LocalProcessLauncher.java
    geode-core/src/main/java/org/apache/geode/management/internal/cli/commands/StartServerCommand.java
    ```


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] geode pull request #699: GEODE-3413: overhaul launcher and process classes a...

Posted by kirklund <gi...@git.apache.org>.
Github user kirklund commented on a diff in the pull request:

    https://github.com/apache/geode/pull/699#discussion_r132542242
  
    --- Diff: geode-core/src/main/java/org/apache/geode/distributed/LocatorLauncher.java ---
    @@ -1075,8 +1082,7 @@ private LocatorState stopWithWorkingDirectory() {
         try {
           final ProcessController controller =
               new ProcessControllerFactory().createProcessController(this.controllerParameters,
    -              new File(getWorkingDirectory()), ProcessType.LOCATOR.getPidFileName(),
    -              READ_PID_FILE_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS);
    +              new File(getWorkingDirectory()), ProcessType.LOCATOR.getPidFileName());
           parsedPid = controller.getProcessId();
     
           // NOTE in-process request will go infinite loop unless we do the following
    --- End diff --
    
    Done.


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] geode pull request #699: GEODE-3413: overhaul launcher and process classes a...

Posted by kirklund <gi...@git.apache.org>.
Github user kirklund commented on a diff in the pull request:

    https://github.com/apache/geode/pull/699#discussion_r132592382
  
    --- Diff: geode-core/src/test/java/org/apache/geode/distributed/LocatorLauncherLocalIntegrationTest.java ---
    @@ -14,745 +14,270 @@
      */
     package org.apache.geode.distributed;
     
    -import org.apache.geode.distributed.AbstractLauncher.Status;
    +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.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.distributed.LocatorLauncher.Builder;
     import org.apache.geode.distributed.LocatorLauncher.LocatorState;
     import org.apache.geode.distributed.internal.InternalLocator;
    -import org.apache.geode.internal.*;
    -import org.apache.geode.internal.net.SocketCreatorFactory;
    +import org.apache.geode.internal.GemFireVersion;
     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.apache.geode.test.junit.runners.CategoryWithParameterizedRunnerFactory;
    -import org.junit.After;
    -import org.junit.Before;
    -import org.junit.Ignore;
    -import org.junit.Test;
    -import org.junit.experimental.categories.Category;
    -import org.junit.runner.RunWith;
    -import org.junit.runners.Parameterized;
    -
    -import java.io.File;
    -import java.lang.management.ManagementFactory;
    -import java.net.BindException;
    -import java.net.InetAddress;
    -
    -import static org.apache.geode.distributed.ConfigurationProperties.*;
    -import static org.junit.Assert.*;
     
     /**
    - * Tests usage of LocatorLauncher as a local API in existing JVM.
    + * Integration tests for using {@link LocatorLauncher} as an in-process API within an existing JVM.
      *
      * @since GemFire 8.0
      */
     @Category(IntegrationTest.class)
    -@RunWith(Parameterized.class)
    -@Parameterized.UseParametersRunnerFactory(CategoryWithParameterizedRunnerFactory.class)
    -public class LocatorLauncherLocalIntegrationTest
    -    extends AbstractLocatorLauncherIntegrationTestCase {
    +public class LocatorLauncherLocalIntegrationTest extends LocatorLauncherIntegrationTestCase {
     
       @Before
    -  public final void setUpLocatorLauncherLocalIntegrationTest() throws Exception {
    +  public void setUpLocatorLauncherLocalIntegrationTest() 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 tearDownLocatorLauncherLocalIntegrationTest() throws Exception {
    +  public void tearDownLocatorLauncherLocalIntegrationTest() throws Exception {
         disconnectFromDS();
       }
     
       @Test
    -  public void testBuilderSetProperties() throws Throwable {
    -    this.launcher = new Builder().setForce(true).setMemberName(getUniqueName())
    -        .setPort(this.locatorPort).setWorkingDirectory(this.workingDirectory)
    -        .set(CLUSTER_CONFIGURATION_DIR, this.clusterConfigDirectory)
    -        .set(DISABLE_AUTO_RECONNECT, "true").set(LOG_LEVEL, "config").set(MCAST_PORT, "0").build();
    -
    -    try {
    -      assertEquals(Status.ONLINE, this.launcher.start().getStatus());
    -      waitForLocatorToStart(this.launcher, true);
    -
    -      final InternalLocator locator = this.launcher.getLocator();
    -      assertNotNull(locator);
    -
    -      final DistributedSystem distributedSystem = locator.getDistributedSystem();
    -
    -      assertNotNull(distributedSystem);
    -      assertEquals("true", distributedSystem.getProperties().getProperty(DISABLE_AUTO_RECONNECT));
    -      assertEquals("0", distributedSystem.getProperties().getProperty(MCAST_PORT));
    -      assertEquals("config", distributedSystem.getProperties().getProperty(LOG_LEVEL));
    -      assertEquals(getUniqueName(), distributedSystem.getProperties().getProperty(NAME));
    -    } catch (Throwable e) {
    -      this.errorCollector.addError(e);
    -    }
    -
    -    try {
    -      assertEquals(Status.STOPPED, this.launcher.stop().getStatus());
    -      assertNull(this.launcher.getLocator());
    -    } catch (Throwable e) {
    -      this.errorCollector.addError(e);
    -    }
    +  public void usesLocatorPortAsDefaultPort() throws Exception {
    +    launcher = givenLocatorLauncher();
    +
    +    assertThat(launcher.getPort()).isEqualTo(defaultLocatorPort);
       }
     
       @Test
    -  public void testIsAttachAPIFound() throws Exception {
    -    final ProcessControllerFactory factory = new ProcessControllerFactory();
    -    assertTrue(factory.isAttachAPIFound());
    +  public void startReturnsOnline() throws Exception {
    +    launcher = givenLocatorLauncher();
    +
    +    assertThat(launcher.start().getStatus()).isEqualTo(ONLINE);
       }
     
       @Test
    -  public void testStartCreatesPidFile() throws Throwable {
    -    this.launcher = new Builder().setMemberName(getUniqueName()).setPort(this.locatorPort)
    -        .setRedirectOutput(true).setWorkingDirectory(this.workingDirectory)
    -        .set(CLUSTER_CONFIGURATION_DIR, this.clusterConfigDirectory).set(LOG_LEVEL, "config")
    -        .build();
    -
    -    try {
    -      this.launcher.start();
    -      waitForLocatorToStart(this.launcher);
    -      assertEquals(Status.ONLINE, this.launcher.status().getStatus());
    -
    -      // validate the pid file and its contents
    -      this.pidFile = new File(this.temporaryFolder.getRoot(), ProcessType.LOCATOR.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 startWithPortUsesPort() throws Exception {
    +    LocatorLauncher launcher = startLocator(newBuilder().setPort(defaultLocatorPort));
    +
    +    assertThat(launcher.getLocator().getPort()).isEqualTo(defaultLocatorPort);
       }
     
       @Test
    -  public void testStartDeletesStaleControlFiles() throws Throwable {
    -    // create existing control files
    -    this.stopRequestFile =
    -        new File(this.temporaryFolder.getRoot(), ProcessType.LOCATOR.getStopRequestFileName());
    -    this.stopRequestFile.createNewFile();
    -    assertTrue(this.stopRequestFile.exists());
    -
    -    this.statusRequestFile =
    -        new File(this.temporaryFolder.getRoot(), ProcessType.LOCATOR.getStatusRequestFileName());
    -    this.statusRequestFile.createNewFile();
    -    assertTrue(this.statusRequestFile.exists());
    -
    -    this.statusFile =
    -        new File(this.temporaryFolder.getRoot(), ProcessType.LOCATOR.getStatusFileName());
    -    this.statusFile.createNewFile();
    -    assertTrue(this.statusFile.exists());
    -
    -    // build and start the locator
    -    final Builder builder = new Builder().setMemberName(getUniqueName()).setPort(this.locatorPort)
    -        .setRedirectOutput(true).setWorkingDirectory(this.workingDirectory)
    -        .set(CLUSTER_CONFIGURATION_DIR, this.clusterConfigDirectory).set(LOG_LEVEL, "config");
    -
    -    assertFalse(builder.getForce());
    -    this.launcher = builder.build();
    -    assertFalse(this.launcher.isForcing());
    -    this.launcher.start();
    -
    -    try {
    -      waitForLocatorToStart(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.LOCATOR.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(stopRequestFile.exists());
    -      assertFalse(statusRequestFile.exists());
    -      assertFalse(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 startWithPortZeroUsesAnEphemeralPort() throws Exception {
    +    LocatorLauncher launcher = startLocator(newBuilder().setPort(0));
    +
    +    assertThat(launcher.getLocator().getPort()).isGreaterThan(0);
    +    assertThat(launcher.getLocator().isPeerLocator()).isTrue();
       }
     
       @Test
    -  public void testStartOverwritesStalePidFile() throws Throwable {
    -    // create existing pid file
    -    this.pidFile = new File(this.temporaryFolder.getRoot(), ProcessType.LOCATOR.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 locator
    -    final Builder builder = new Builder().setMemberName(getUniqueName()).setPort(this.locatorPort)
    -        .setRedirectOutput(true).setWorkingDirectory(this.workingDirectory)
    -        .set(CLUSTER_CONFIGURATION_DIR, this.clusterConfigDirectory).set(LOG_LEVEL, "config");
    -
    -    assertFalse(builder.getForce());
    -    this.launcher = builder.build();
    -    assertFalse(this.launcher.isForcing());
    -    this.launcher.start();
    -
    -    try {
    -      waitForLocatorToStart(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 startUsesBuilderValues() throws Exception {
    +    LocatorLauncher launcher = startLocator(newBuilder().setPort(nonDefaultLocatorPort));
    +
    +    InternalLocator locator = launcher.getLocator();
    +    assertThat(locator.getPort()).isEqualTo(nonDefaultLocatorPort);
    +
    +    DistributedSystem system = locator.getDistributedSystem();
    +    assertThat(system.getProperties().getProperty(DISABLE_AUTO_RECONNECT)).isEqualTo("true");
    +    assertThat(system.getProperties().getProperty(LOG_LEVEL)).isEqualTo("config");
    +    assertThat(system.getProperties().getProperty(MCAST_PORT)).isEqualTo("0");
    +    assertThat(system.getProperties().getProperty(NAME)).isEqualTo(getUniqueName());
       }
     
       @Test
    -  @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.LOCATOR.getPidFileName());
    -   * final int realPid = Host.getHost(0).getVM(3).invoke(() -> ProcessUtils.identifyPid());
    -   * assertFalse(realPid == ProcessUtils.identifyPid()); writePid(this.pidFile, realPid);
    -   * 
    -   * // build and start the locator final Builder builder = new Builder() .setForce(true)
    -   * .setMemberName(getUniqueName()) .setPort(this.locatorPort) .setRedirectOutput(true)
    -   * 
    -   * assertTrue(builder.getForce()); this.launcher = builder.build();
    -   * assertTrue(this.launcher.isForcing()); this.launcher.start();
    -   * 
    -   * // collect and throw the FIRST failure Throwable failure = null;
    -   * 
    -   * try { waitForLocatorToStart(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 startCreatesPidFile() throws Exception {
    +    startLocator();
    +
    +    assertThat(getPidFile()).exists();
    +  }
    +
    +  @Test
    +  public void pidFileContainsServerPid() throws Exception {
    +    startLocator();
    +
    +    assertThat(getLocatorPid()).isEqualTo(localPid);
    +  }
    +
    +  @Test
    +  public void startDeletesStaleControlFiles() throws Exception {
    +    File stopRequestFile = givenControlFile(getProcessType().getStopRequestFileName());
    +    File statusRequestFile = givenControlFile(getProcessType().getStatusRequestFileName());
    +    File statusFile = givenControlFile(getProcessType().getStatusFileName());
    +
    +    startLocator();
    +
    +    assertDeletionOf(stopRequestFile);
    +    assertDeletionOf(statusRequestFile);
    +    assertDeletionOf(statusFile);
    +  }
     
       @Test
    -  public void testStartWithDefaultPortInUseFails() throws Throwable {
    -    // Test makes no sense in this case
    -    if (this.locatorPort == 0) {
    -      return;
    -    }
    -
    -    this.socket =
    -        SocketCreatorFactory.getSocketCreatorForComponent(SecurableCommunicationChannel.CLUSTER)
    -            .createServerSocket(this.locatorPort, 50, null, -1);
    -    assertTrue(this.socket.isBound());
    -    assertFalse(this.socket.isClosed());
    -    assertFalse(AvailablePort.isPortAvailable(this.locatorPort, AvailablePort.SOCKET));
    -
    -    assertNotNull(System.getProperty(DistributionLocator.TEST_OVERRIDE_DEFAULT_PORT_PROPERTY));
    -    assertEquals(this.locatorPort,
    -        Integer.valueOf(System.getProperty(DistributionLocator.TEST_OVERRIDE_DEFAULT_PORT_PROPERTY))
    -            .intValue());
    -    assertFalse(AvailablePort.isPortAvailable(this.locatorPort, AvailablePort.SOCKET));
    -
    -    this.launcher = new Builder().setMemberName(getUniqueName()).setRedirectOutput(true)
    -        .setWorkingDirectory(this.workingDirectory)
    -        .set(CLUSTER_CONFIGURATION_DIR, this.clusterConfigDirectory).set(LOG_LEVEL, "config")
    -        .build();
    -
    -    assertEquals(this.locatorPort, this.launcher.getPort().intValue());
    -
    -    RuntimeException expected = null;
    -    try {
    -      this.launcher.start();
    -
    -      // why did it not fail like it's supposed to?
    -      final String property =
    -          System.getProperty(DistributionLocator.TEST_OVERRIDE_DEFAULT_PORT_PROPERTY);
    -      assertNotNull(property);
    -      assertEquals(this.locatorPort, Integer.valueOf(property).intValue());
    -      assertFalse(AvailablePort.isPortAvailable(this.locatorPort, AvailablePort.SOCKET));
    -      assertEquals(this.locatorPort, this.launcher.getPort().intValue());
    -      assertEquals(this.locatorPort, this.socket.getLocalPort());
    -      assertTrue(this.socket.isBound());
    -      assertFalse(this.socket.isClosed());
    -
    -      fail("LocatorLauncher 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.LOCATOR.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...
    -    LocatorState 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 startOverwritesStalePidFile() throws Exception {
    +    givenPidFile(fakePid);
    +
    +    startLocator();
    +
    +    assertThat(getLocatorPid()).isNotEqualTo(fakePid);
       }
     
       @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.LOCATOR.getPidFileName());
    -                          * writePid(this.pidFile, realPid);
    -                          * 
    -                          * // build and start the locator final Builder builder = new Builder()
    -                          * .setMemberName(getUniqueName()) .setPort(this.locatorPort)
    -                          * .setRedirectOutput(true) .set(logLevel, "config");
    -                          * 
    -                          * 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("LocatorLauncher start should have thrown RuntimeException caused by FileAlreadyExistsException"
    -                          * ); } catch (RuntimeException e) { expected = e;
    -                          * assertNotNull(expected.getMessage()); assertTrue(expected.getMessage(),
    -                          * expected.getMessage().
    -                          * contains("A PID file already exists and a Locator may be running in"));
    -                          * assertIndexDetailsEquals(RuntimeException.class, expected.getClass()); }
    -                          * catch (Throwable e) { logger.error(e); if (failure == null) { failure =
    -                          * e; } }
    -                          * 
    -                          * // just in case the launcher started... LocatorState 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.locator.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 startWithDefaultPortInUseFailsWithBindException() throws Exception {
    +    givenLocatorPortInUse(defaultLocatorPort);
    +
    +    launcher = new Builder().build();
    +
    +    assertThatThrownBy(() -> launcher.start()).isInstanceOf(RuntimeException.class)
    +        .hasCauseInstanceOf(BindException.class);
    +  }
     
       @Test
    -  public void testStartUsingPort() throws Throwable {
    -    // generate one free port and then use it instead of default
    -    final int freeTCPPort = AvailablePortHelper.getRandomAvailableTCPPort();
    -    assertTrue(AvailablePort.isPortAvailable(freeTCPPort, AvailablePort.SOCKET));
    -
    -    this.launcher = new Builder().setMemberName(getUniqueName()).setPort(freeTCPPort)
    -        .setRedirectOutput(true).setWorkingDirectory(this.workingDirectory)
    -        .set(CLUSTER_CONFIGURATION_DIR, this.clusterConfigDirectory).set(LOG_LEVEL, "config")
    -        .build();
    -
    -    int pid = 0;
    -    try {
    -      // if start succeeds without throwing exception then #47778 is fixed
    -      this.launcher.start();
    -      waitForLocatorToStart(this.launcher);
    -
    -      // validate the pid file and its contents
    -      this.pidFile = new File(this.temporaryFolder.getRoot(), ProcessType.LOCATOR.getPidFileName());
    -      assertTrue(pidFile.exists());
    -      pid = readPid(pidFile);
    -      assertTrue(pid > 0);
    -      assertTrue(ProcessUtils.isProcessAlive(pid));
    -      assertEquals(getPid(), pid);
    -
    -      // verify locator did not use default port
    -      assertTrue(AvailablePort.isPortAvailable(this.locatorPort, AvailablePort.SOCKET));
    -
    -      final LocatorState status = this.launcher.status();
    -      final String portString = status.getPort();
    -      assertEquals("Port should be \"" + freeTCPPort + "\" instead of " + portString,
    -          String.valueOf(freeTCPPort), portString);
    -    } catch (Throwable e) {
    -      this.errorCollector.addError(e);
    -    }
    -
    -    // stop the locator
    -    try {
    -      assertEquals(Status.STOPPED, this.launcher.stop().getStatus());
    -      waitForFileToDelete(this.pidFile);
    -    } catch (Throwable e) {
    -      this.errorCollector.addError(e);
    -    }
    +  public void startWithLocatorPortInUseFailsWithBindException() throws Exception {
    +    givenServerPortInUse(nonDefaultLocatorPort);
    +
    +    launcher = new Builder().setPort(nonDefaultLocatorPort).build();
    +
    +    assertThatThrownBy(() -> this.launcher.start()).isInstanceOf(RuntimeException.class)
    +        .hasCauseInstanceOf(BindException.class);
       }
     
       @Test
    -  public void testStartUsingPortInUseFails() throws Throwable {
    -    // Test makes no sense in this case
    -    if (this.locatorPort == 0) {
    -      return;
    -    }
    -
    -    // generate one free port and then use it instead of default
    -    this.socket =
    -        SocketCreatorFactory.getSocketCreatorForComponent(SecurableCommunicationChannel.CLUSTER)
    -            .createServerSocket(this.locatorPort, 50, null, -1);
    -
    -    this.launcher = new Builder().setMemberName(getUniqueName()).setPort(this.locatorPort)
    -        .setRedirectOutput(true).setWorkingDirectory(this.workingDirectory)
    -        .set(CLUSTER_CONFIGURATION_DIR, this.clusterConfigDirectory).set(LOG_LEVEL, "config")
    -        .build();
    -
    -    RuntimeException expected = null;
    -    try {
    -      this.launcher.start();
    -      fail("LocatorLauncher 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.LOCATOR.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...
    -    LocatorState 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 statusWithPidReturnsOnlineWithDetails() throws Exception {
    +    givenRunningLocator();
    +
    +    LocatorState locatorState = new Builder().setPid(localPid).build().status();
    +
    +    assertThat(locatorState.getStatus()).isEqualTo(ONLINE);
    +    assertThat(locatorState.getClasspath()).isEqualTo(getClassPath());
    +    assertThat(locatorState.getGemFireVersion()).isEqualTo(GemFireVersion.getGemFireVersion());
    +    assertThat(locatorState.getHost()).isEqualTo(InetAddress.getLocalHost().getCanonicalHostName());
    --- End diff --
    
    It could fail in the Geode Nightly Build too. We'll have to keep an eye on this...


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] geode pull request #699: GEODE-3413: overhaul launcher and process classes a...

Posted by kirklund <gi...@git.apache.org>.
Github user kirklund commented on a diff in the pull request:

    https://github.com/apache/geode/pull/699#discussion_r132532669
  
    --- Diff: geode-core/src/test/java/org/apache/geode/internal/process/AbstractProcessStreamReaderIntegrationTest.java ---
    @@ -0,0 +1,234 @@
    +/*
    + * 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.internal.process;
    +
    +import static java.util.concurrent.TimeUnit.MILLISECONDS;
    +import static org.apache.commons.lang.SystemUtils.LINE_SEPARATOR;
    +
    +import java.io.File;
    +import java.util.ArrayList;
    +import java.util.Arrays;
    +import java.util.List;
    +
    +import org.awaitility.Awaitility;
    +import org.awaitility.core.ConditionFactory;
    +import org.junit.After;
    +
    +import org.apache.geode.internal.util.StopWatch;
    +
    +/**
    + * Abstract base class for functional integration testing of {@link ProcessStreamReader}.
    + */
    +public abstract class AbstractProcessStreamReaderIntegrationTest {
    +
    +  /** Timeout to join to a running ProcessStreamReader thread */
    +  protected static final int READER_JOIN_TIMEOUT_MILLIS = 20 * 1000;
    +
    +  /** Sleep timeout for {@link ProcessSleeps} instead of sleeping Long.MAX_VALUE */
    +  private static final int PROCESS_FAILSAFE_TIMEOUT_MILLIS = 10 * 60 * 1000;
    +
    +  /** Additional time for launched processes to live before terminating */
    +  private static final int PROCESS_TIME_TO_LIVE_MILLIS = 3 * 500;
    +
    +  /** Timeout to wait for a new {@link ProcessStreamReader} to be running */
    +  private static final int WAIT_FOR_READER_IS_RUNNING_TIMEOUT_MILLIS = 20 * 1000;
    +
    +  protected Process process;
    +  protected ProcessStreamReader stderr;
    +  protected ProcessStreamReader stdout;
    +
    +  @After
    +  public void afterProcessStreamReaderTestCase() throws Exception {
    +    if (stderr != null) {
    +      stderr.stop();
    +    }
    +    if (stdout != null) {
    +      stdout.stop();
    +    }
    +    if (process != null) {
    +      try {
    +        process.getErrorStream().close();
    +        process.getInputStream().close();
    +        process.getOutputStream().close();
    +      } finally {
    +        // this is async and can require more than 10 seconds on slower machines
    +        process.destroy();
    +      }
    +    }
    +  }
    +
    +  protected ConditionFactory await() {
    +    return Awaitility.await().atMost(WAIT_FOR_READER_IS_RUNNING_TIMEOUT_MILLIS, MILLISECONDS);
    +  }
    +
    +  protected static boolean isAlive(final Process process) {
    --- End diff --
    
    Done.


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] geode pull request #699: GEODE-3413: overhaul launcher and process classes a...

Posted by jaredjstewart <gi...@git.apache.org>.
Github user jaredjstewart commented on a diff in the pull request:

    https://github.com/apache/geode/pull/699#discussion_r132568184
  
    --- Diff: geode-core/src/main/java/org/apache/geode/distributed/LocatorLauncher.java ---
    @@ -1352,11 +1328,13 @@ protected void parseCommand(final String... args) {
          * @see org.apache.geode.distributed.LocatorLauncher.Command#isCommand(String)
          * @see #parseArguments(String...)
          */
    -    protected void parseMemberName(final String[] args) {
    -      for (String arg : args) {
    -        if (!(arg.startsWith(OPTION_PREFIX) || Command.isCommand(arg))) {
    -          setMemberName(arg);
    -          break;
    +    protected void parseMemberName(final String... args) {
    +      if (args != null) {
    +        for (String arg : args) {
    +          if (!(arg.startsWith(OPTION_PREFIX) || Command.isCommand(arg))) {
    --- End diff --
    
    I believe the behavior of this method may contradicts its javadoc, which says that
    > If the argument does **not** start with '-' or is **not** the name of a Locator launcher command, then the value is presumed to be the member name for the Locator in GemFire.
    
    Whereas the actual implementation seems to find values which **are** the name of a Locator launcher command.  I would guess that the javadoc is correct about the intended behavior.
    <hr>
    
    P.S. I can't resist writing this in a declarative style with streams :)
    ```
    protected void parseMemberName(final String... args) {
      if (args == null) return;
    
      Arrays.stream(args)
          .filter(arg -> !(arg.startsWith(OPTION_PREFIX) || Command.isCommand(arg)))
          .findFirst()
          .ifPresent(this::setMemberName);
    }
    ```


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] geode pull request #699: GEODE-3413: overhaul launcher and process classes a...

Posted by PurelyApplied <gi...@git.apache.org>.
Github user PurelyApplied commented on a diff in the pull request:

    https://github.com/apache/geode/pull/699#discussion_r132312583
  
    --- Diff: geode-core/src/main/java/org/apache/geode/distributed/AbstractLauncher.java ---
    @@ -502,7 +507,7 @@ protected static Integer identifyPid() {
           }
         }
     
    -    // TODO refactor the logic in this method into a DateTimeFormatUtils class
    +    // consider refactoring the logic in this method into a DateTimeFormatUtils class
    --- End diff --
    
    I'd remove this and the line 510 comments altogether.  If the suggestion has value, we should open a ticket for it.
    
    Likewise `LocatorLauncher:382`, `ServerLauncher:523`


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] geode pull request #699: GEODE-3413: overhaul launcher and process classes a...

Posted by PurelyApplied <gi...@git.apache.org>.
Github user PurelyApplied commented on a diff in the pull request:

    https://github.com/apache/geode/pull/699#discussion_r132312668
  
    --- Diff: geode-core/src/main/java/org/apache/geode/distributed/LocatorLauncher.java ---
    @@ -1848,8 +1884,7 @@ public LocatorLauncher build() {
         private final String name;
     
         Command(final String name, final String... options) {
    -      assert !StringUtils
    -          .isBlank(name) : "The name of the locator launcher command must be specified!";
    +      assert !isBlank(name) : "The name of the locator launcher command must be specified!";
    --- End diff --
    
    As long as we're touching this, we could consider using `isNotBlank` for better readability.


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] geode pull request #699: GEODE-3413: overhaul launcher and process classes a...

Posted by kirklund <gi...@git.apache.org>.
Github user kirklund commented on a diff in the pull request:

    https://github.com/apache/geode/pull/699#discussion_r132541795
  
    --- Diff: geode-core/src/main/java/org/apache/geode/internal/process/MBeanProcessController.java ---
    @@ -228,9 +230,9 @@ private void disconnect() {
        * @throws PidUnavailableException if parsing the pid from the RuntimeMXBean name fails
        */
       boolean checkPidMatches() throws IllegalStateException, IOException, PidUnavailableException {
    --- End diff --
    
    Deleted.


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] geode pull request #699: GEODE-3413: overhaul launcher and process classes a...

Posted by kirklund <gi...@git.apache.org>.
Github user kirklund commented on a diff in the pull request:

    https://github.com/apache/geode/pull/699#discussion_r132308711
  
    --- Diff: geode-core/src/test/java/org/apache/geode/distributed/AbstractLauncherIntegrationTest.java ---
    @@ -47,26 +50,21 @@
     
       @Before
       public void setUp() throws Exception {
    -    this.gemfirePropertiesFile =
    -        this.temporaryFolder.newFile(DistributionConfig.GEMFIRE_PREFIX + "properties");
    +    propertiesFile = temporaryFolder.newFile(GEMFIRE_PREFIX + "properties");
     
    -    this.expectedGemfireProperties = new Properties();
    -    this.expectedGemfireProperties.setProperty(NAME, "memberOne");
    -    this.expectedGemfireProperties.setProperty(GROUPS, "groupOne, groupTwo");
    -    this.expectedGemfireProperties.store(new FileWriter(this.gemfirePropertiesFile, false),
    -        this.testName.getMethodName());
    +    expectedProperties = new Properties();
    +    expectedProperties.setProperty(NAME, "memberOne");
    +    expectedProperties.setProperty(GROUPS, "groupOne, groupTwo");
    +    expectedProperties.store(new FileWriter(propertiesFile, false), testName.getMethodName());
     
    -    assertThat(this.gemfirePropertiesFile).isNotNull();
    -    assertThat(this.gemfirePropertiesFile.exists()).isTrue();
    -    assertThat(this.gemfirePropertiesFile.isFile()).isTrue();
    +    assertThat(propertiesFile).exists().isFile();
       }
     
       @Test
    -  public void testLoadGemFirePropertiesFromFile() throws Exception {
    -    final Properties actualGemFireProperties =
    -        AbstractLauncher.loadGemFireProperties(this.gemfirePropertiesFile.toURI().toURL());
    +  public void loadGemFirePropertiesFromFile() throws Exception {
    +    Properties loadedProperties = loadGemFireProperties(propertiesFile.toURI().toURL());
     
    -    assertThat(actualGemFireProperties).isNotNull();
    -    assertThat(actualGemFireProperties).isEqualTo(this.expectedGemfireProperties);
    +    assertThat(loadedProperties).isEqualTo(expectedProperties);
       }
    +
    --- End diff --
    
    Removed from all classes in change-set.


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] geode pull request #699: GEODE-3413: overhaul launcher and process classes a...

Posted by kirklund <gi...@git.apache.org>.
Github user kirklund commented on a diff in the pull request:

    https://github.com/apache/geode/pull/699#discussion_r132532641
  
    --- Diff: geode-core/src/test/java/org/apache/geode/internal/process/FileProcessControllerIntegrationTest.java ---
    @@ -0,0 +1,243 @@
    +/*
    + * 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.internal.process;
    +
    +import static com.googlecode.catchexception.CatchException.caughtException;
    +import static com.googlecode.catchexception.CatchException.verifyException;
    +import static java.util.concurrent.TimeUnit.MILLISECONDS;
    +import static java.util.concurrent.TimeUnit.MINUTES;
    +import static org.assertj.core.api.Assertions.assertThat;
    +import static org.assertj.core.api.Assertions.assertThatThrownBy;
    +import static org.mockito.Mockito.mock;
    +import static org.mockito.Mockito.when;
    +
    +import java.io.File;
    +import java.util.concurrent.ExecutorService;
    +import java.util.concurrent.Executors;
    +import java.util.concurrent.TimeoutException;
    +import java.util.concurrent.atomic.AtomicReference;
    +
    +import org.awaitility.Awaitility;
    +import org.awaitility.core.ConditionFactory;
    +import org.junit.After;
    +import org.junit.Before;
    +import org.junit.Ignore;
    +import org.junit.Rule;
    +import org.junit.Test;
    +import org.junit.experimental.categories.Category;
    +import org.junit.rules.ErrorCollector;
    +import org.junit.rules.TemporaryFolder;
    +import org.junit.rules.TestName;
    +
    +import org.apache.geode.distributed.AbstractLauncher.Status;
    +import org.apache.geode.distributed.LocatorLauncher;
    +import org.apache.geode.distributed.LocatorLauncher.Builder;
    +import org.apache.geode.distributed.LocatorLauncher.LocatorState;
    +import org.apache.geode.internal.process.io.EmptyFileWriter;
    +import org.apache.geode.internal.process.io.IntegerFileWriter;
    +import org.apache.geode.internal.process.io.StringFileWriter;
    +import org.apache.geode.test.junit.categories.IntegrationTest;
    +
    +/**
    + * Integration tests for {@link FileProcessController}.
    + */
    +@Category(IntegrationTest.class)
    +public class FileProcessControllerIntegrationTest {
    +
    +  private static final String STATUS_JSON = generateStatusJson();
    +
    +  private final AtomicReference<String> statusRef = new AtomicReference<>();
    +
    +  private File pidFile;
    +  private File statusFile;
    +  private File statusRequestFile;
    +  private File stopRequestFile;
    +  private int pid;
    +  private FileControllerParameters params;
    +  private ExecutorService executor;
    +
    +  @Rule
    +  public ErrorCollector errorCollector = new ErrorCollector();
    +
    +  @Rule
    +  public TemporaryFolder temporaryFolder = new TemporaryFolder();
    +
    +  @Rule
    +  public TestName testName = new TestName();
    +
    +  @Before
    +  public void setUp() throws Exception {
    +    ProcessType processType = ProcessType.LOCATOR;
    +    File directory = temporaryFolder.getRoot();
    +    pidFile = new File(directory, processType.getPidFileName());
    +    statusFile = new File(directory, processType.getStatusFileName());
    +    statusRequestFile = new File(directory, processType.getStatusRequestFileName());
    +    stopRequestFile = new File(directory, processType.getStopRequestFileName());
    +    pid = ProcessUtils.identifyPid();
    +
    +    params = mock(FileControllerParameters.class);
    +    when(params.getPidFile()).thenReturn(pidFile);
    +    when(params.getProcessId()).thenReturn(pid);
    +    when(params.getProcessType()).thenReturn(processType);
    +    when(params.getDirectory()).thenReturn(temporaryFolder.getRoot());
    +
    +    executor = Executors.newSingleThreadExecutor();
    +  }
    +
    +  @After
    +  public void tearDown() throws Exception {
    +    assertThat(executor.shutdownNow()).isEmpty();
    +  }
    +
    +  @Test
    +  public void statusShouldAwaitTimeoutWhileFileIsEmpty() throws Exception {
    +    // given: FileProcessController with empty pidFile
    +    FileProcessController controller = new FileProcessController(params, pid, 10, MILLISECONDS);
    +
    +    // when:
    +    verifyException(controller).status();
    +
    +    // then: we expect TimeoutException to be thrown
    +    assertThat((Exception) caughtException()).isInstanceOf(TimeoutException.class)
    +        .hasMessageContaining("Timed out waiting for process to create").hasNoCause();
    +  }
    +
    +  @Test
    +  public void statusShouldReturnJsonFromStatusFile() throws Exception {
    +    // given: FileProcessController with pidFile containing real pid
    +    new IntegerFileWriter(pidFile).writeToFile(pid);
    +    FileProcessController controller = new FileProcessController(params, pid, 2, MINUTES);
    +
    +    // when: status is called in one thread
    +    executor.execute(() -> {
    +      try {
    +        statusRef.set(controller.status());
    +      } catch (Exception e) {
    +        errorCollector.addError(e);
    +      }
    +    });
    +
    +    // and: json is written to the status file
    +    new StringFileWriter(statusFile).writeToFile(STATUS_JSON);
    +
    +    // then: returned status should be the json in the file
    +    await().until(() -> assertThat(statusRef.get()).isEqualTo(STATUS_JSON));
    +  }
    +
    +  @Ignore // GEODE-3278
    --- End diff --
    
    Done.


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] geode pull request #699: GEODE-3413: overhaul launcher and process classes a...

Posted by pdxrunner <gi...@git.apache.org>.
Github user pdxrunner commented on a diff in the pull request:

    https://github.com/apache/geode/pull/699#discussion_r132515331
  
    --- Diff: geode-core/src/main/java/org/apache/geode/distributed/ServerLauncher.java ---
    @@ -810,9 +819,6 @@ public void setStatus(final String statusMessage) {
                 LocalizedStrings.Launcher_Command_START_PID_UNAVAILABLE_ERROR_MESSAGE.toLocalizedString(
                     getServiceName(), getId(), getWorkingDirectory(), e.getMessage()),
                 e);
    -      } catch (ClusterConfigurationNotAvailableException e) {
    -        failOnStart(e);
    -        throw e;
           } catch (RuntimeException e) {
             failOnStart(e);
    --- End diff --
    
    Opportunity to combine catch blocks?


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] geode pull request #699: GEODE-3413: overhaul launcher and process classes a...

Posted by pdxrunner <gi...@git.apache.org>.
Github user pdxrunner commented on a diff in the pull request:

    https://github.com/apache/geode/pull/699#discussion_r132287600
  
    --- Diff: geode-core/src/test/java/org/apache/geode/distributed/AbstractLauncherTest.java ---
    @@ -14,253 +14,370 @@
      */
     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, "");
    --- End diff --
    
    For consistency with following tests use 'StringUtils.EMPTY' instead of '""'.


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] geode pull request #699: GEODE-3413: overhaul launcher and process classes a...

Posted by kirklund <gi...@git.apache.org>.
Github user kirklund commented on a diff in the pull request:

    https://github.com/apache/geode/pull/699#discussion_r132321738
  
    --- Diff: geode-core/src/test/java/org/apache/geode/distributed/ServerLauncherRemoteIntegrationTestCase.java ---
    @@ -0,0 +1,270 @@
    +/*
    + * 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.LOG_LEVEL;
    +import static org.apache.geode.distributed.ConfigurationProperties.MCAST_PORT;
    +import static org.apache.geode.distributed.internal.DistributionConfig.GEMFIRE_PREFIX;
    +import static org.apache.geode.internal.cache.AbstractCacheServer.TEST_OVERRIDE_DEFAULT_PORT_PROPERTY;
    +import static org.apache.geode.internal.process.ProcessUtils.isProcessAlive;
    +import static org.assertj.core.api.Assertions.assertThat;
    +
    +import java.io.File;
    +import java.io.IOException;
    +import java.io.UncheckedIOException;
    +import java.net.BindException;
    +import java.util.ArrayList;
    +import java.util.List;
    +import java.util.concurrent.atomic.AtomicBoolean;
    +
    +import org.junit.After;
    +import org.junit.Before;
    +
    +import org.apache.geode.distributed.AbstractLauncher.Status;
    +import org.apache.geode.internal.process.ProcessStreamReader;
    +import org.apache.geode.internal.process.ProcessStreamReader.InputListener;
    +
    +/**
    + * Abstract base class for integration tests of {@link ServerLauncher} as an application main in a
    + * forked JVM.
    + *
    + * @since GemFire 8.0
    + */
    +public abstract class ServerLauncherRemoteIntegrationTestCase
    +    extends ServerLauncherIntegrationTestCase implements UsesServerCommand {
    +
    +  private final AtomicBoolean threwBindException = new AtomicBoolean();
    +
    +  protected volatile Process process;
    +  protected volatile ProcessStreamReader processOutReader;
    +  protected volatile ProcessStreamReader processErrReader;
    +
    +  private ServerCommand serverCommand;
    +
    +  @Before
    +  public void setUp() throws Exception {
    +    serverCommand = new ServerCommand(this);
    +  }
    +
    +  @After
    +  public 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
    +  public List<String> getJvmArguments() {
    +    List<String> jvmArguments = new ArrayList<>();
    +    jvmArguments.add("-D" + GEMFIRE_PREFIX + LOG_LEVEL + "=config");
    +    jvmArguments.add("-D" + GEMFIRE_PREFIX + MCAST_PORT + "=0");
    +    jvmArguments
    +        .add("-D" + TEST_OVERRIDE_DEFAULT_PORT_PROPERTY + "=" + String.valueOf(defaultServerPort));
    +    return jvmArguments;
    +  }
    +
    +  @Override
    +  public String getName() {
    +    return getUniqueName();
    +  }
    +
    +  @Override
    +  public boolean getDisableDefaultServer() {
    +    return false;
    +  }
    +
    +  protected void assertThatServerThrewBindException() {
    +    assertThat(threwBindException.get()).isTrue();
    +  }
    +
    +  protected void assertThatServerThrew(final Class<? extends Throwable> throwableClass) {
    +    assertThat(threwBindException.get()).isTrue();
    +  }
    +
    +  protected ServerLauncher startServer(final ServerCommand command) {
    +    return awaitStart(command);
    +  }
    +
    +  protected ServerLauncher awaitStart(final ServerCommand command,
    +      final ProcessStreamReader.InputListener outListener,
    +      final ProcessStreamReader.InputListener errListener) throws Exception {
    +    executeCommandWithReaders(command.create(), outListener, errListener);
    +    ServerLauncher launcher = awaitStart(getWorkingDirectory());
    +    assertThat(process.isAlive()).isTrue();
    +    return launcher;
    +  }
    +
    +  protected ServerLauncher awaitStart(final ServerCommand command) {
    +    try {
    +      executeCommandWithReaders(command);
    +      ServerLauncher launcher = awaitStart(getWorkingDirectory());
    +      assertThat(process.isAlive()).isTrue();
    +      return launcher;
    +    } catch (IOException e) {
    +      throw new UncheckedIOException(e);
    +    }
    +  }
    +
    +  protected ServerLauncher awaitStart(final File workingDirectory) {
    +    try {
    +      this.launcher = new ServerLauncher.Builder()
    +          .setWorkingDirectory(workingDirectory.getCanonicalPath()).build();
    +      ServerLauncher launcher = awaitStart(this.launcher);
    +      assertThat(process.isAlive()).isTrue();
    +      return launcher;
    +    } catch (IOException e) {
    +      throw new UncheckedIOException(e);
    +    }
    +  }
    +
    +  @Override
    +  protected ServerLauncher awaitStart(final ServerLauncher launcher) {
    +    await().until(() -> assertThat(launcher.status().getStatus()).isEqualTo(Status.ONLINE));
    +    assertThat(process.isAlive()).isTrue();
    +    return launcher;
    +  }
    +
    +  protected ServerLauncher awaitStart() {
    --- End diff --
    
    Delete unused method.


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] geode pull request #699: GEODE-3413: overhaul launcher and process classes a...

Posted by jaredjstewart <gi...@git.apache.org>.
Github user jaredjstewart commented on a diff in the pull request:

    https://github.com/apache/geode/pull/699#discussion_r132585334
  
    --- Diff: geode-core/src/main/java/org/apache/geode/internal/process/LocalProcessLauncher.java ---
    @@ -96,33 +117,55 @@ void close() {
        * @throws IOException if unable to create or write to the file
        */
       private void writePid(final boolean force) throws FileAlreadyExistsException, IOException {
    -    final boolean created = this.pidFile.createNewFile();
    -    if (!created && !force) {
    -      int otherPid = 0;
    -      try {
    -        otherPid = ProcessUtils.readPid(this.pidFile);
    -      } catch (IOException e) {
    -        // suppress
    -      } catch (NumberFormatException e) {
    -        // suppress
    -      }
    -      boolean ignorePidFile = false;
    -      if (otherPid != 0 && !ignoreIsPidAlive()) {
    -        ignorePidFile = !ProcessUtils.isProcessAlive(otherPid);
    -      }
    -      if (!ignorePidFile) {
    -        throw new FileAlreadyExistsException("Pid file already exists: " + this.pidFile + " for "
    -            + (otherPid > 0 ? "process " + otherPid : "unknown process"));
    +    if (this.pidFile.exists()) {
    +      if (!force) {
    +        checkOtherPid(readOtherPid());
           }
    +      this.pidFile.delete();
    +    }
    +
    +    assert !this.pidFile.exists();
    --- End diff --
    
    I saw that you used Apache common's `Validate` class in other places.  Would that be good to use here since the default java `assert` won't do anything under normal circumstances?


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] geode pull request #699: GEODE-3413: overhaul launcher and process classes a...

Posted by kirklund <gi...@git.apache.org>.
Github user kirklund commented on a diff in the pull request:

    https://github.com/apache/geode/pull/699#discussion_r132542016
  
    --- Diff: geode-core/src/test/java/org/apache/geode/internal/process/BlockingProcessStreamReaderIntegrationTest.java ---
    @@ -0,0 +1,179 @@
    +/*
    + * 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.internal.process;
    +
    +import static org.apache.geode.internal.lang.SystemUtils.isWindows;
    +import static org.apache.geode.internal.process.ProcessUtils.isProcessAlive;
    +import static org.assertj.core.api.Assertions.assertThat;
    +import static org.junit.Assume.assumeFalse;
    +
    +import org.junit.Before;
    +import org.junit.Test;
    +import org.junit.experimental.categories.Category;
    +
    +import org.apache.geode.internal.process.ProcessStreamReader.Builder;
    +import org.apache.geode.internal.process.ProcessStreamReader.ReadingMode;
    +import org.apache.geode.test.junit.categories.IntegrationTest;
    +
    +/**
    + * Functional integration tests for BlockingProcessStreamReader. All tests are skipped on Windows
    + * due to TRAC bug #51967 which is caused by a JDK bug. See
    --- End diff --
    
    I added description.


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] geode pull request #699: GEODE-3413: overhaul launcher and process classes a...

Posted by pdxrunner <gi...@git.apache.org>.
Github user pdxrunner commented on a diff in the pull request:

    https://github.com/apache/geode/pull/699#discussion_r132314473
  
    --- Diff: geode-core/src/test/java/org/apache/geode/distributed/LauncherIntegrationTestCase.java ---
    @@ -0,0 +1,505 @@
    +/*
    + * 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.nio.file.Files;
    +import java.util.List;
    +import java.util.Properties;
    +import java.util.concurrent.Callable;
    +import java.util.concurrent.atomic.AtomicBoolean;
    +
    +import org.apache.commons.lang.StringUtils;
    +import org.apache.logging.log4j.Logger;
    +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.logging.LogService;
    +import org.apache.geode.internal.net.SocketCreatorFactory;
    +import org.apache.geode.internal.process.PidUnavailableException;
    +import org.apache.geode.internal.process.ProcessStreamReader.InputListener;
    +import org.apache.geode.internal.process.ProcessType;
    +import org.apache.geode.internal.process.ProcessUtils;
    +import org.apache.geode.internal.process.lang.AvailablePid;
    +import org.apache.geode.internal.util.StopWatch;
    +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 {
    +  protected static final Logger logger = LogService.getLogger();
    +
    +  protected static final int WAIT_FOR_PROCESS_TO_DIE_TIMEOUT = 5 * 60 * 1000; // 5 minutes
    +  protected static final int TIMEOUT_MILLISECONDS = WAIT_FOR_PROCESS_TO_DIE_TIMEOUT;
    +  protected static final int WAIT_FOR_FILE_CREATION_TIMEOUT = 10 * 1000; // 10s
    +  protected static final int WAIT_FOR_FILE_DELETION_TIMEOUT = 10 * 1000; // 10s
    +  protected static final int WAIT_FOR_MBEAN_TIMEOUT = 10 * 1000; // 10s
    +  protected static final int INTERVAL_MILLISECONDS = 100;
    +
    +  protected static final int PREFERRED_FAKE_PID = 42;
    +
    +  private static final String EXPECTED_EXCEPTION_ADD =
    +      "<ExpectedException action=add>{}</ExpectedException>";
    +  private static final String EXPECTED_EXCEPTION_REMOVE =
    --- End diff --
    
    Unused fields?


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] geode pull request #699: GEODE-3413: overhaul launcher and process classes a...

Posted by kirklund <gi...@git.apache.org>.
Github user kirklund commented on a diff in the pull request:

    https://github.com/apache/geode/pull/699#discussion_r132326281
  
    --- Diff: geode-core/src/test/java/org/apache/geode/internal/process/lang/AvailablePidTest.java ---
    @@ -0,0 +1,74 @@
    +/*
    + * 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.internal.process.lang;
    --- End diff --
    
    ```java
      @Test(timeout = DEFAULT_TIMEOUT_MILLIS)
      public void findAvailablePidShouldReturnRandomPid() throws Exception {
        Random random = spy(new Random());
        availablePid = new AvailablePid(random, DEFAULT_TIMEOUT_MILLIS);
    
        availablePid.findAvailablePid();
    
        verify(random, atLeastOnce()).nextInt(anyInt());
      }
    ```


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] geode pull request #699: GEODE-3413: overhaul launcher and process classes a...

Posted by jaredjstewart <gi...@git.apache.org>.
Github user jaredjstewart commented on a diff in the pull request:

    https://github.com/apache/geode/pull/699#discussion_r132585045
  
    --- Diff: geode-core/src/main/java/org/apache/geode/internal/process/FileProcessController.java ---
    @@ -112,56 +119,43 @@ private void stop(final File workingDir, final String stopRequestFileName) throw
       private String status(final File workingDir, final String statusRequestFileName,
           final String statusFileName) throws IOException, InterruptedException, TimeoutException {
         // monitor for statusFile
    -    final File statusFile = new File(workingDir, statusFileName);
    -    final AtomicReference<String> statusRef = new AtomicReference<>();
    -
    -    final ControlRequestHandler statusHandler = new ControlRequestHandler() {
    -      @Override
    -      public void handleRequest() throws IOException {
    -        // read the statusFile
    -        final BufferedReader reader = new BufferedReader(new FileReader(statusFile));
    -        final StringBuilder lines = new StringBuilder();
    -        try {
    -          String line = null;
    -          while ((line = reader.readLine()) != null) {
    -            lines.append(line);
    -          }
    -        } finally {
    -          statusRef.set(lines.toString());
    -          reader.close();
    +    File statusFile = new File(workingDir, statusFileName);
    +    AtomicReference<String> statusRef = new AtomicReference<>();
    +
    +    ControlRequestHandler statusHandler = () -> {
    --- End diff --
    
    This might be a nice simplification:
    
    ```
    ControlRequestHandler statusHandler = () -> {
          // read the statusFile
          StringBuilder lines = new StringBuilder();
          try (BufferedReader reader = new BufferedReader(new FileReader(statusFile))) {
            reader.lines().forEach(lines::append);
          } finally {
            statusRef.set(lines.toString());
          }
        };
    ```


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] geode pull request #699: GEODE-3413: overhaul launcher and process classes a...

Posted by pdxrunner <gi...@git.apache.org>.
Github user pdxrunner commented on a diff in the pull request:

    https://github.com/apache/geode/pull/699#discussion_r132501696
  
    --- Diff: geode-core/src/test/java/org/apache/geode/internal/process/mbean/Process.java ---
    @@ -16,7 +16,6 @@
     
     /**
      * Extracted from LocalProcessControllerDUnitTest.
    - * 
      */
    --- End diff --
    
    This javadoc doesn't seem meaningful.


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] geode pull request #699: GEODE-3413: overhaul launcher and process classes a...

Posted by jaredjstewart <gi...@git.apache.org>.
Github user jaredjstewart commented on a diff in the pull request:

    https://github.com/apache/geode/pull/699#discussion_r132570355
  
    --- Diff: geode-core/src/main/java/org/apache/geode/distributed/LocatorLauncher.java ---
    @@ -104,6 +109,8 @@
         helpMap.put("bind-address",
    --- End diff --
    
    Since this class is rather large, maybe in the future we can extract the `helpMap` and `usageMap` to a separate class like `LocatorLauncherHelp` whose single responsibility is to provide the help and usage information.


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] geode pull request #699: GEODE-3413: overhaul launcher and process classes a...

Posted by kirklund <gi...@git.apache.org>.
Github user kirklund commented on a diff in the pull request:

    https://github.com/apache/geode/pull/699#discussion_r132305098
  
    --- Diff: geode-core/src/test/java/org/apache/geode/internal/process/AbstractProcessStreamReaderIntegrationTest.java ---
    @@ -0,0 +1,234 @@
    +/*
    + * 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.internal.process;
    +
    +import static java.util.concurrent.TimeUnit.MILLISECONDS;
    +import static org.apache.commons.lang.SystemUtils.LINE_SEPARATOR;
    +
    +import java.io.File;
    +import java.util.ArrayList;
    +import java.util.Arrays;
    +import java.util.List;
    +
    +import org.awaitility.Awaitility;
    +import org.awaitility.core.ConditionFactory;
    +import org.junit.After;
    +
    +import org.apache.geode.internal.util.StopWatch;
    +
    +/**
    + * Abstract base class for functional integration testing of {@link ProcessStreamReader}.
    + */
    +public abstract class AbstractProcessStreamReaderIntegrationTest {
    +
    +  /** Timeout to join to a running ProcessStreamReader thread */
    +  protected static final int READER_JOIN_TIMEOUT_MILLIS = 20 * 1000;
    +
    +  /** Sleep timeout for {@link ProcessSleeps} instead of sleeping Long.MAX_VALUE */
    +  private static final int PROCESS_FAILSAFE_TIMEOUT_MILLIS = 10 * 60 * 1000;
    +
    +  /** Additional time for launched processes to live before terminating */
    +  private static final int PROCESS_TIME_TO_LIVE_MILLIS = 3 * 500;
    +
    +  /** Timeout to wait for a new {@link ProcessStreamReader} to be running */
    +  private static final int WAIT_FOR_READER_IS_RUNNING_TIMEOUT_MILLIS = 20 * 1000;
    +
    +  protected Process process;
    +  protected ProcessStreamReader stderr;
    +  protected ProcessStreamReader stdout;
    +
    +  @After
    +  public void afterProcessStreamReaderTestCase() throws Exception {
    +    if (stderr != null) {
    +      stderr.stop();
    +    }
    +    if (stdout != null) {
    +      stdout.stop();
    +    }
    +    if (process != null) {
    +      try {
    +        process.getErrorStream().close();
    +        process.getInputStream().close();
    +        process.getOutputStream().close();
    +      } finally {
    +        // this is async and can require more than 10 seconds on slower machines
    +        process.destroy();
    +      }
    +    }
    +  }
    +
    +  protected ConditionFactory await() {
    +    return Awaitility.await().atMost(WAIT_FOR_READER_IS_RUNNING_TIMEOUT_MILLIS, MILLISECONDS);
    +  }
    +
    +  protected static boolean isAlive(final Process process) {
    --- End diff --
    
    All callers to this method should now be changed to use the new API instead of this old hack:
    ```java
    process.isAlive()
    ```



---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] geode pull request #699: GEODE-3413: overhaul launcher and process classes a...

Posted by PurelyApplied <gi...@git.apache.org>.
Github user PurelyApplied commented on a diff in the pull request:

    https://github.com/apache/geode/pull/699#discussion_r132311304
  
    --- Diff: geode-core/src/main/java/org/apache/geode/internal/process/MBeanProcessController.java ---
    @@ -228,9 +230,9 @@ private void disconnect() {
        * @throws PidUnavailableException if parsing the pid from the RuntimeMXBean name fails
        */
       boolean checkPidMatches() throws IllegalStateException, IOException, PidUnavailableException {
    --- End diff --
    
    This appears to be unused?  The JavaDoc has it as "NOT USED EXCEPT IN TEST."  This is perhaps no longer true?


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] geode pull request #699: GEODE-3413: overhaul launcher and process classes a...

Posted by kirklund <gi...@git.apache.org>.
Github user kirklund commented on a diff in the pull request:

    https://github.com/apache/geode/pull/699#discussion_r132545900
  
    --- Diff: geode-core/src/main/java/org/apache/geode/distributed/ServerLauncher.java ---
    @@ -810,9 +819,6 @@ public void setStatus(final String statusMessage) {
                 LocalizedStrings.Launcher_Command_START_PID_UNAVAILABLE_ERROR_MESSAGE.toLocalizedString(
                     getServiceName(), getId(), getWorkingDirectory(), e.getMessage()),
                 e);
    -      } catch (ClusterConfigurationNotAvailableException e) {
    -        failOnStart(e);
    -        throw e;
           } catch (RuntimeException e) {
             failOnStart(e);
    --- End diff --
    
    Combined.


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] geode pull request #699: GEODE-3413: overhaul launcher and process classes a...

Posted by kirklund <gi...@git.apache.org>.
Github user kirklund commented on a diff in the pull request:

    https://github.com/apache/geode/pull/699#discussion_r132598899
  
    --- Diff: geode-core/src/main/java/org/apache/geode/distributed/LocatorLauncher.java ---
    @@ -104,6 +109,8 @@
         helpMap.put("bind-address",
    --- End diff --
    
    I'd love to break these Launcher classes up into smaller classes. I'd also like to move them from org.apache.geode.distributed -- I don't think that pkg really makes sense for these classes to live in.


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] geode pull request #699: GEODE-3413: overhaul launcher and process classes a...

Posted by kirklund <gi...@git.apache.org>.
Github user kirklund commented on a diff in the pull request:

    https://github.com/apache/geode/pull/699#discussion_r132542204
  
    --- Diff: geode-core/src/test/java/org/apache/geode/distributed/ServerLauncherRemoteIntegrationTestCase.java ---
    @@ -0,0 +1,270 @@
    +/*
    + * 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.LOG_LEVEL;
    +import static org.apache.geode.distributed.ConfigurationProperties.MCAST_PORT;
    +import static org.apache.geode.distributed.internal.DistributionConfig.GEMFIRE_PREFIX;
    +import static org.apache.geode.internal.cache.AbstractCacheServer.TEST_OVERRIDE_DEFAULT_PORT_PROPERTY;
    +import static org.apache.geode.internal.process.ProcessUtils.isProcessAlive;
    +import static org.assertj.core.api.Assertions.assertThat;
    +
    +import java.io.File;
    +import java.io.IOException;
    +import java.io.UncheckedIOException;
    +import java.net.BindException;
    +import java.util.ArrayList;
    +import java.util.List;
    +import java.util.concurrent.atomic.AtomicBoolean;
    +
    +import org.junit.After;
    +import org.junit.Before;
    +
    +import org.apache.geode.distributed.AbstractLauncher.Status;
    +import org.apache.geode.internal.process.ProcessStreamReader;
    +import org.apache.geode.internal.process.ProcessStreamReader.InputListener;
    +
    +/**
    + * Abstract base class for integration tests of {@link ServerLauncher} as an application main in a
    + * forked JVM.
    + *
    + * @since GemFire 8.0
    + */
    +public abstract class ServerLauncherRemoteIntegrationTestCase
    +    extends ServerLauncherIntegrationTestCase implements UsesServerCommand {
    +
    +  private final AtomicBoolean threwBindException = new AtomicBoolean();
    +
    +  protected volatile Process process;
    +  protected volatile ProcessStreamReader processOutReader;
    +  protected volatile ProcessStreamReader processErrReader;
    +
    +  private ServerCommand serverCommand;
    +
    +  @Before
    +  public void setUp() throws Exception {
    +    serverCommand = new ServerCommand(this);
    +  }
    +
    +  @After
    +  public 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
    +  public List<String> getJvmArguments() {
    +    List<String> jvmArguments = new ArrayList<>();
    +    jvmArguments.add("-D" + GEMFIRE_PREFIX + LOG_LEVEL + "=config");
    +    jvmArguments.add("-D" + GEMFIRE_PREFIX + MCAST_PORT + "=0");
    +    jvmArguments
    +        .add("-D" + TEST_OVERRIDE_DEFAULT_PORT_PROPERTY + "=" + String.valueOf(defaultServerPort));
    +    return jvmArguments;
    +  }
    +
    +  @Override
    +  public String getName() {
    +    return getUniqueName();
    +  }
    +
    +  @Override
    +  public boolean getDisableDefaultServer() {
    +    return false;
    +  }
    +
    +  protected void assertThatServerThrewBindException() {
    +    assertThat(threwBindException.get()).isTrue();
    +  }
    +
    +  protected void assertThatServerThrew(final Class<? extends Throwable> throwableClass) {
    +    assertThat(threwBindException.get()).isTrue();
    +  }
    +
    +  protected ServerLauncher startServer(final ServerCommand command) {
    +    return awaitStart(command);
    +  }
    +
    +  protected ServerLauncher awaitStart(final ServerCommand command,
    +      final ProcessStreamReader.InputListener outListener,
    +      final ProcessStreamReader.InputListener errListener) throws Exception {
    +    executeCommandWithReaders(command.create(), outListener, errListener);
    +    ServerLauncher launcher = awaitStart(getWorkingDirectory());
    +    assertThat(process.isAlive()).isTrue();
    +    return launcher;
    +  }
    +
    +  protected ServerLauncher awaitStart(final ServerCommand command) {
    +    try {
    +      executeCommandWithReaders(command);
    +      ServerLauncher launcher = awaitStart(getWorkingDirectory());
    +      assertThat(process.isAlive()).isTrue();
    +      return launcher;
    +    } catch (IOException e) {
    +      throw new UncheckedIOException(e);
    +    }
    +  }
    +
    +  protected ServerLauncher awaitStart(final File workingDirectory) {
    +    try {
    +      this.launcher = new ServerLauncher.Builder()
    +          .setWorkingDirectory(workingDirectory.getCanonicalPath()).build();
    +      ServerLauncher launcher = awaitStart(this.launcher);
    +      assertThat(process.isAlive()).isTrue();
    +      return launcher;
    +    } catch (IOException e) {
    +      throw new UncheckedIOException(e);
    +    }
    +  }
    +
    +  @Override
    +  protected ServerLauncher awaitStart(final ServerLauncher launcher) {
    +    await().until(() -> assertThat(launcher.status().getStatus()).isEqualTo(Status.ONLINE));
    +    assertThat(process.isAlive()).isTrue();
    +    return launcher;
    +  }
    +
    +  protected ServerLauncher awaitStart() {
    +    return awaitStart(this.launcher);
    +  }
    +
    +  protected void awaitStop() {
    +    await().until(() -> assertThat(this.process.isAlive()).isFalse());
    +  }
    +
    +  protected void assertStopOf(final Process process) {
    +    await().until(() -> assertThat(process.isAlive()).isFalse());
    +  }
    +
    +  protected Process getServerProcess() {
    +    return this.process;
    +  }
    +
    +  protected void startServerShouldFail(final ServerCommand command, final InputListener outListener,
    +      final InputListener errListener) throws IOException, InterruptedException {
    +    executeCommandWithReaders(command.create(), outListener, errListener);
    +    process.waitFor(2, MINUTES);
    +    assertThat(process.isAlive()).isFalse();
    +    assertThat(process.exitValue()).isEqualTo(1);
    +  }
    +
    +  protected void startServerShouldFail(final ServerCommand command)
    +      throws IOException, InterruptedException {
    +    startServerShouldFail(command, createBindExceptionListener("sysout", threwBindException),
    +        createBindExceptionListener("syserr", threwBindException));
    +  }
    +
    +  protected void startServerShouldFail() throws IOException, InterruptedException {
    +    startServerShouldFail(serverCommand);
    +  }
    +
    +  private InputListener createBindExceptionListener(final String name,
    +      final AtomicBoolean threwBindException) {
    +    return createExpectedListener(name, getUniqueName() + "#" + name, BindException.class.getName(),
    +        threwBindException);
    +  }
    +
    +  @Override
    +  protected ServerLauncher startServer() {
    +    return startServer(serverCommand);
    +  }
    +
    +  protected void assertThatProcessIsNotAlive() {
    +    assertThatProcessIsNotAlive(process);
    +  }
    +
    +  protected void assertThatProcessIsNotAlive(final Process process) {
    +    assertThat(process.isAlive()).isFalse();
    +  }
    +
    +  protected void assertProcessIsNotAlive() {
    +    assertThat(process.isAlive()).isFalse();
    +  }
    +
    +  protected void assertProcessIsAlive() {
    --- End diff --
    
    All unused methods deleted.


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] geode pull request #699: GEODE-3413: overhaul launcher and process classes a...

Posted by kirklund <gi...@git.apache.org>.
Github user kirklund commented on a diff in the pull request:

    https://github.com/apache/geode/pull/699#discussion_r132599768
  
    --- Diff: geode-core/src/main/java/org/apache/geode/internal/process/FileProcessController.java ---
    @@ -112,56 +119,43 @@ private void stop(final File workingDir, final String stopRequestFileName) throw
       private String status(final File workingDir, final String statusRequestFileName,
           final String statusFileName) throws IOException, InterruptedException, TimeoutException {
         // monitor for statusFile
    -    final File statusFile = new File(workingDir, statusFileName);
    -    final AtomicReference<String> statusRef = new AtomicReference<>();
    -
    -    final ControlRequestHandler statusHandler = new ControlRequestHandler() {
    -      @Override
    -      public void handleRequest() throws IOException {
    -        // read the statusFile
    -        final BufferedReader reader = new BufferedReader(new FileReader(statusFile));
    -        final StringBuilder lines = new StringBuilder();
    -        try {
    -          String line = null;
    -          while ((line = reader.readLine()) != null) {
    -            lines.append(line);
    -          }
    -        } finally {
    -          statusRef.set(lines.toString());
    -          reader.close();
    +    File statusFile = new File(workingDir, statusFileName);
    +    AtomicReference<String> statusRef = new AtomicReference<>();
    +
    +    ControlRequestHandler statusHandler = () -> {
    --- End diff --
    
    Done.


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] geode pull request #699: GEODE-3413: overhaul launcher and process classes a...

Posted by pdxrunner <gi...@git.apache.org>.
Github user pdxrunner commented on a diff in the pull request:

    https://github.com/apache/geode/pull/699#discussion_r132303567
  
    --- Diff: geode-core/src/test/java/org/apache/geode/internal/process/BlockingProcessStreamReaderWindowsTest.java ---
    @@ -0,0 +1,97 @@
    +/*
    + * 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.internal.process;
    +
    +import static org.apache.geode.internal.lang.SystemUtils.isWindows;
    +import static org.assertj.core.api.Assertions.assertThat;
    +import static org.assertj.core.api.Assertions.assertThatThrownBy;
    +import static org.junit.Assume.assumeTrue;
    +
    +import java.util.concurrent.ExecutorService;
    +import java.util.concurrent.Executors;
    +import java.util.concurrent.Future;
    +import java.util.concurrent.TimeUnit;
    +import java.util.concurrent.TimeoutException;
    +
    +import org.junit.After;
    +import org.junit.Before;
    +import org.junit.Test;
    +import org.junit.experimental.categories.Category;
    +
    +import org.apache.geode.test.junit.categories.IntegrationTest;
    +
    +/**
    + * Functional integration test {@link #hangsOnWindows} for BlockingProcessStreamReader which
    + * verifies TRAC #51967 on Windows. The hang is caused by a JDK bug in which a thread invoking
    --- End diff --
    
    The bug number reference is not meaningful in the context of the geode community. I suggest rewording this to remove the specific reference while still describing the the nature of the bug that this test verifies the fix for.


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] geode pull request #699: GEODE-3413: overhaul launcher and process classes a...

Posted by pdxrunner <gi...@git.apache.org>.
Github user pdxrunner commented on a diff in the pull request:

    https://github.com/apache/geode/pull/699#discussion_r132301005
  
    --- Diff: geode-core/src/test/java/org/apache/geode/internal/process/lang/AvailablePidTest.java ---
    @@ -0,0 +1,74 @@
    +/*
    + * 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.internal.process.lang;
    --- End diff --
    
    Ideally there would be a test for 'findAvailablePid(existing processPid)' returns a random pid. 


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] geode pull request #699: GEODE-3413: overhaul launcher and process classes a...

Posted by kirklund <gi...@git.apache.org>.
Github user kirklund commented on a diff in the pull request:

    https://github.com/apache/geode/pull/699#discussion_r132599242
  
    --- Diff: geode-core/src/main/java/org/apache/geode/distributed/LocatorLauncher.java ---
    @@ -1352,11 +1328,13 @@ protected void parseCommand(final String... args) {
          * @see org.apache.geode.distributed.LocatorLauncher.Command#isCommand(String)
          * @see #parseArguments(String...)
          */
    -    protected void parseMemberName(final String[] args) {
    -      for (String arg : args) {
    -        if (!(arg.startsWith(OPTION_PREFIX) || Command.isCommand(arg))) {
    -          setMemberName(arg);
    -          break;
    +    protected void parseMemberName(final String... args) {
    +      if (args != null) {
    +        for (String arg : args) {
    +          if (!(arg.startsWith(OPTION_PREFIX) || Command.isCommand(arg))) {
    --- End diff --
    
    We need to refactor these classes a lot more. I only copied line 1332 from ServerLauncher which then indented the rest of the lines. I made sure that everything was more consistent. LocatorLauncher threw NPE if args was null but ServerLauncher was ok with null.


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] geode pull request #699: GEODE-3413: overhaul launcher and process classes a...

Posted by kirklund <gi...@git.apache.org>.
Github user kirklund commented on a diff in the pull request:

    https://github.com/apache/geode/pull/699#discussion_r132321779
  
    --- Diff: geode-core/src/test/java/org/apache/geode/distributed/ServerLauncherRemoteIntegrationTestCase.java ---
    @@ -0,0 +1,270 @@
    +/*
    + * 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.LOG_LEVEL;
    +import static org.apache.geode.distributed.ConfigurationProperties.MCAST_PORT;
    +import static org.apache.geode.distributed.internal.DistributionConfig.GEMFIRE_PREFIX;
    +import static org.apache.geode.internal.cache.AbstractCacheServer.TEST_OVERRIDE_DEFAULT_PORT_PROPERTY;
    +import static org.apache.geode.internal.process.ProcessUtils.isProcessAlive;
    +import static org.assertj.core.api.Assertions.assertThat;
    +
    +import java.io.File;
    +import java.io.IOException;
    +import java.io.UncheckedIOException;
    +import java.net.BindException;
    +import java.util.ArrayList;
    +import java.util.List;
    +import java.util.concurrent.atomic.AtomicBoolean;
    +
    +import org.junit.After;
    +import org.junit.Before;
    +
    +import org.apache.geode.distributed.AbstractLauncher.Status;
    +import org.apache.geode.internal.process.ProcessStreamReader;
    +import org.apache.geode.internal.process.ProcessStreamReader.InputListener;
    +
    +/**
    + * Abstract base class for integration tests of {@link ServerLauncher} as an application main in a
    + * forked JVM.
    + *
    + * @since GemFire 8.0
    + */
    +public abstract class ServerLauncherRemoteIntegrationTestCase
    +    extends ServerLauncherIntegrationTestCase implements UsesServerCommand {
    +
    +  private final AtomicBoolean threwBindException = new AtomicBoolean();
    +
    +  protected volatile Process process;
    +  protected volatile ProcessStreamReader processOutReader;
    +  protected volatile ProcessStreamReader processErrReader;
    +
    +  private ServerCommand serverCommand;
    +
    +  @Before
    +  public void setUp() throws Exception {
    +    serverCommand = new ServerCommand(this);
    +  }
    +
    +  @After
    +  public 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
    +  public List<String> getJvmArguments() {
    +    List<String> jvmArguments = new ArrayList<>();
    +    jvmArguments.add("-D" + GEMFIRE_PREFIX + LOG_LEVEL + "=config");
    +    jvmArguments.add("-D" + GEMFIRE_PREFIX + MCAST_PORT + "=0");
    +    jvmArguments
    +        .add("-D" + TEST_OVERRIDE_DEFAULT_PORT_PROPERTY + "=" + String.valueOf(defaultServerPort));
    +    return jvmArguments;
    +  }
    +
    +  @Override
    +  public String getName() {
    +    return getUniqueName();
    +  }
    +
    +  @Override
    +  public boolean getDisableDefaultServer() {
    +    return false;
    +  }
    +
    +  protected void assertThatServerThrewBindException() {
    +    assertThat(threwBindException.get()).isTrue();
    +  }
    +
    +  protected void assertThatServerThrew(final Class<? extends Throwable> throwableClass) {
    +    assertThat(threwBindException.get()).isTrue();
    +  }
    +
    +  protected ServerLauncher startServer(final ServerCommand command) {
    +    return awaitStart(command);
    +  }
    +
    +  protected ServerLauncher awaitStart(final ServerCommand command,
    +      final ProcessStreamReader.InputListener outListener,
    +      final ProcessStreamReader.InputListener errListener) throws Exception {
    +    executeCommandWithReaders(command.create(), outListener, errListener);
    +    ServerLauncher launcher = awaitStart(getWorkingDirectory());
    +    assertThat(process.isAlive()).isTrue();
    +    return launcher;
    +  }
    +
    +  protected ServerLauncher awaitStart(final ServerCommand command) {
    +    try {
    +      executeCommandWithReaders(command);
    +      ServerLauncher launcher = awaitStart(getWorkingDirectory());
    +      assertThat(process.isAlive()).isTrue();
    +      return launcher;
    +    } catch (IOException e) {
    +      throw new UncheckedIOException(e);
    +    }
    +  }
    +
    +  protected ServerLauncher awaitStart(final File workingDirectory) {
    +    try {
    +      this.launcher = new ServerLauncher.Builder()
    +          .setWorkingDirectory(workingDirectory.getCanonicalPath()).build();
    +      ServerLauncher launcher = awaitStart(this.launcher);
    +      assertThat(process.isAlive()).isTrue();
    +      return launcher;
    +    } catch (IOException e) {
    +      throw new UncheckedIOException(e);
    +    }
    +  }
    +
    +  @Override
    +  protected ServerLauncher awaitStart(final ServerLauncher launcher) {
    +    await().until(() -> assertThat(launcher.status().getStatus()).isEqualTo(Status.ONLINE));
    +    assertThat(process.isAlive()).isTrue();
    +    return launcher;
    +  }
    +
    +  protected ServerLauncher awaitStart() {
    +    return awaitStart(this.launcher);
    +  }
    +
    +  protected void awaitStop() {
    +    await().until(() -> assertThat(this.process.isAlive()).isFalse());
    +  }
    +
    +  protected void assertStopOf(final Process process) {
    +    await().until(() -> assertThat(process.isAlive()).isFalse());
    +  }
    +
    +  protected Process getServerProcess() {
    +    return this.process;
    +  }
    +
    +  protected void startServerShouldFail(final ServerCommand command, final InputListener outListener,
    +      final InputListener errListener) throws IOException, InterruptedException {
    +    executeCommandWithReaders(command.create(), outListener, errListener);
    +    process.waitFor(2, MINUTES);
    +    assertThat(process.isAlive()).isFalse();
    +    assertThat(process.exitValue()).isEqualTo(1);
    +  }
    +
    +  protected void startServerShouldFail(final ServerCommand command)
    +      throws IOException, InterruptedException {
    +    startServerShouldFail(command, createBindExceptionListener("sysout", threwBindException),
    +        createBindExceptionListener("syserr", threwBindException));
    +  }
    +
    +  protected void startServerShouldFail() throws IOException, InterruptedException {
    +    startServerShouldFail(serverCommand);
    +  }
    +
    +  private InputListener createBindExceptionListener(final String name,
    +      final AtomicBoolean threwBindException) {
    +    return createExpectedListener(name, getUniqueName() + "#" + name, BindException.class.getName(),
    +        threwBindException);
    +  }
    +
    +  @Override
    +  protected ServerLauncher startServer() {
    +    return startServer(serverCommand);
    +  }
    +
    +  protected void assertThatProcessIsNotAlive() {
    --- End diff --
    
    Delete unused method.


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] geode pull request #699: GEODE-3413: overhaul launcher and process classes a...

Posted by kirklund <gi...@git.apache.org>.
Github user kirklund commented on a diff in the pull request:

    https://github.com/apache/geode/pull/699#discussion_r132322055
  
    --- Diff: geode-core/src/test/java/org/apache/geode/distributed/AbstractLauncherTest.java ---
    @@ -14,253 +14,370 @@
      */
     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 isSetReturnsFalseIfPropertyHasRealValue() 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)).isTrue();
       }
     
       @Test
    -  public void testLoadGemFirePropertiesWithNullURL() {
    -    final Properties properties = AbstractLauncher.loadGemFireProperties(null);
    -    assertNotNull(properties);
    -    assertTrue(properties.isEmpty());
    +  public void isSetKeyIsCaseSensitive() throws Exception {
    +    Properties properties = new Properties();
    +
    +    properties.setProperty(NAME, "memberOne");
    +
    +    assertThat(AbstractLauncher.isSet(properties, "NaMe")).isFalse();
       }
     
       @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 loadGemFirePropertiesWithNullURLReturnsEmptyProperties() throws Exception {
    +    URL nullUrl = null;
    +
    +    Properties properties = AbstractLauncher.loadGemFireProperties(nullUrl);
    +
    +    assertThat(properties).isNotNull().isEmpty();
       }
     
       @Test
    -  public void testGetDistributedSystemProperties() {
    -    AbstractLauncher<?> launcher = createAbstractLauncher("memberOne", "1");
    +  public void loadGemFirePropertiesWithNonExistingURLReturnsEmptyProperties() throws Exception {
    +    URL nonExistingUrl = new URL("file:///path/to/non_existing/gemfire.properties");
    +
    +    Properties properties = AbstractLauncher.loadGemFireProperties(nonExistingUrl);
     
    -    assertNotNull(launcher);
    -    assertEquals("1", launcher.getMemberId());
    -    assertEquals("memberOne", launcher.getMemberName());
    +    assertThat(properties).isNotNull().isEmpty();
    +  }
     
    -    Properties distributedSystemProperties = launcher.getDistributedSystemProperties();
    +  @Test
    +  public void abstractLauncherHasMemberIdAndMemberName() throws Exception {
    --- End diff --
    
    Deleted.


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] geode pull request #699: GEODE-3413: overhaul launcher and process classes a...

Posted by kirklund <gi...@git.apache.org>.
Github user kirklund commented on a diff in the pull request:

    https://github.com/apache/geode/pull/699#discussion_r132299177
  
    --- Diff: geode-core/src/main/java/org/apache/geode/config/internal/ClusterConfigurationNotAvailableException.java ---
    @@ -0,0 +1,29 @@
    +/*
    + * 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.config.internal;
    --- End diff --
    
    Do we want to use org.apache.geode.internal.config instead?


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] geode pull request #699: GEODE-3413: overhaul launcher and process classes a...

Posted by jaredjstewart <gi...@git.apache.org>.
Github user jaredjstewart commented on a diff in the pull request:

    https://github.com/apache/geode/pull/699#discussion_r132569537
  
    --- Diff: geode-core/src/main/java/org/apache/geode/distributed/LocatorLauncher.java ---
    @@ -1781,8 +1782,8 @@ protected void validate() {
          * @see org.apache.geode.distributed.LocatorLauncher.Command#START
          */
         protected void validateOnStart() {
    -      if (Command.START.equals(getCommand())) {
    -        if (StringUtils.isBlank(getMemberName())
    +      if (Command.START == getCommand()) {
    --- End diff --
    
    Cool, I didn't know that `==` could be used safely for enums.


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] geode pull request #699: GEODE-3413: overhaul launcher and process classes a...

Posted by kirklund <gi...@git.apache.org>.
Github user kirklund commented on a diff in the pull request:

    https://github.com/apache/geode/pull/699#discussion_r132592102
  
    --- Diff: geode-core/src/test/java/org/apache/geode/internal/process/NonBlockingProcessStreamReaderIntegrationTest.java ---
    @@ -0,0 +1,182 @@
    +/*
    + * 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.internal.process;
    +
    +import static org.apache.geode.internal.process.ProcessStreamReader.ReadingMode.NON_BLOCKING;
    +import static org.apache.geode.internal.process.ProcessUtils.isProcessAlive;
    +import static org.assertj.core.api.Assertions.assertThat;
    +
    +import org.junit.Before;
    +import org.junit.Test;
    +import org.junit.experimental.categories.Category;
    +
    +import org.apache.geode.internal.process.ProcessStreamReader.Builder;
    +import org.apache.geode.test.junit.categories.IntegrationTest;
    +
    +/**
    + * Functional integration tests for NonBlockingProcessStreamReader which was introduced to fix TRAC
    + * #51967.
    + *
    + * @see BlockingProcessStreamReaderIntegrationTest
    + * @see BlockingProcessStreamReaderWindowsTest
    + *
    + * @since GemFire 8.2
    + */
    +@Category(IntegrationTest.class)
    +public class NonBlockingProcessStreamReaderIntegrationTest
    +    extends BaseProcessStreamReaderIntegrationTest {
    +
    +  private StringBuffer stdoutBuffer;
    +  private StringBuffer stderrBuffer;
    +
    +  @Before
    +  public void before() {
    +    stdoutBuffer = new StringBuffer();
    +    stderrBuffer = new StringBuffer();
    +  }
    +
    +  /**
    +   * This test hangs on Windows if the implementation is blocking instead of non-blocking.
    +   */
    +  @Test
    +  public void canCloseStreamsWhileProcessIsAlive() throws Exception {
    +    // arrange
    +    process = new ProcessBuilder(createCommandLine(ProcessSleeps.class)).start();
    +    stdout = new Builder(process).inputStream(process.getInputStream()).readingMode(NON_BLOCKING)
    +        .build().start();
    +    stderr = new Builder(process).inputStream(process.getErrorStream()).readingMode(NON_BLOCKING)
    --- End diff --
    
    Done.


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] geode pull request #699: GEODE-3413: overhaul launcher and process classes a...

Posted by pdxrunner <gi...@git.apache.org>.
Github user pdxrunner commented on a diff in the pull request:

    https://github.com/apache/geode/pull/699#discussion_r132315473
  
    --- Diff: geode-core/src/test/java/org/apache/geode/distributed/LauncherIntegrationTestCase.java ---
    @@ -0,0 +1,505 @@
    +/*
    + * 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.nio.file.Files;
    +import java.util.List;
    +import java.util.Properties;
    +import java.util.concurrent.Callable;
    +import java.util.concurrent.atomic.AtomicBoolean;
    +
    +import org.apache.commons.lang.StringUtils;
    +import org.apache.logging.log4j.Logger;
    +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.logging.LogService;
    +import org.apache.geode.internal.net.SocketCreatorFactory;
    +import org.apache.geode.internal.process.PidUnavailableException;
    +import org.apache.geode.internal.process.ProcessStreamReader.InputListener;
    +import org.apache.geode.internal.process.ProcessType;
    +import org.apache.geode.internal.process.ProcessUtils;
    +import org.apache.geode.internal.process.lang.AvailablePid;
    +import org.apache.geode.internal.util.StopWatch;
    +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 {
    +  protected static final Logger logger = LogService.getLogger();
    +
    +  protected static final int WAIT_FOR_PROCESS_TO_DIE_TIMEOUT = 5 * 60 * 1000; // 5 minutes
    +  protected static final int TIMEOUT_MILLISECONDS = WAIT_FOR_PROCESS_TO_DIE_TIMEOUT;
    +  protected static final int WAIT_FOR_FILE_CREATION_TIMEOUT = 10 * 1000; // 10s
    +  protected static final int WAIT_FOR_FILE_DELETION_TIMEOUT = 10 * 1000; // 10s
    +  protected static final int WAIT_FOR_MBEAN_TIMEOUT = 10 * 1000; // 10s
    +  protected static final int INTERVAL_MILLISECONDS = 100;
    +
    +  protected static final int PREFERRED_FAKE_PID = 42;
    +
    +  private static final String EXPECTED_EXCEPTION_ADD =
    +      "<ExpectedException action=add>{}</ExpectedException>";
    +  private static final String EXPECTED_EXCEPTION_REMOVE =
    +      "<ExpectedException action=remove>{}</ExpectedException>";
    +  private static final String EXPECTED_EXCEPTION_MBEAN_NOT_REGISTERED =
    +      "MBean Not Registered In GemFire Domain";
    +
    +  private IgnoredException ignoredException;
    +
    +  protected int localPid;
    +  protected int fakePid;
    +
    +  protected volatile ServerSocket socket;
    +
    +  protected volatile File pidFile;
    +  protected volatile File stopRequestFile;
    +  protected volatile File statusRequestFile;
    +  protected volatile File statusFile;
    +
    +  @Rule
    +  public TestName testName = new TestName();
    +
    +  @Rule
    +  public RestoreSystemProperties restoreSystemProperties = new RestoreSystemProperties();
    +
    +  @Rule
    +  public TemporaryFolder temporaryFolder = new TemporaryFolder();
    +
    +  @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 (this.socket != null) {
    +      this.socket.close();
    +      this.socket = null;
    +    }
    +    delete(this.pidFile);
    +    delete(this.stopRequestFile);
    +    delete(this.statusRequestFile);
    +    delete(this.statusFile);
    +  }
    +
    +  protected abstract ProcessType getProcessType();
    +
    +  protected String getStopRequestFileName() {
    +    return getProcessType().getStopRequestFileName();
    +  }
    +
    +  protected String getStatusRequestFileName() {
    +    return getProcessType().getStatusRequestFileName();
    +  }
    +
    +  protected String getStatusFileName() {
    +    return getProcessType().getStatusFileName();
    +  }
    +
    +  protected void givenEmptyWorkingDirectory() {
    +    assertThat(getWorkingDirectory().listFiles()).hasSize(0);
    +  }
    +
    +  protected List<String> getJvmArguments() {
    +    return ManagementFactory.getRuntimeMXBean().getInputArguments();
    +  }
    +
    +  protected ConditionFactory await() {
    +    return Awaitility.await().atMost(2, MINUTES);
    +  }
    +
    +  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 File getPidFile() {
    +    return new File(getWorkingDirectory(), getProcessType().getPidFileName());
    +  }
    +
    +  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 getWorkingDirectory() {
    +    return this.temporaryFolder.getRoot();
    +  }
    +
    +  protected String getWorkingDirectoryPath() {
    +    try {
    +      return getWorkingDirectory().getCanonicalPath();
    +    } catch (IOException e) {
    +      throw new UncheckedIOException(e);
    +    }
    +  }
    +
    +  protected void createPidFile(final Object content) {
    --- End diff --
    
    IDE flags several unused methods


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] geode pull request #699: GEODE-3413: overhaul launcher and process classes a...

Posted by pdxrunner <gi...@git.apache.org>.
Github user pdxrunner commented on a diff in the pull request:

    https://github.com/apache/geode/pull/699#discussion_r132314337
  
    --- Diff: geode-core/src/test/java/org/apache/geode/distributed/LauncherIntegrationTestCase.java ---
    @@ -0,0 +1,505 @@
    +/*
    + * 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.nio.file.Files;
    +import java.util.List;
    +import java.util.Properties;
    +import java.util.concurrent.Callable;
    +import java.util.concurrent.atomic.AtomicBoolean;
    +
    +import org.apache.commons.lang.StringUtils;
    +import org.apache.logging.log4j.Logger;
    +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.logging.LogService;
    +import org.apache.geode.internal.net.SocketCreatorFactory;
    +import org.apache.geode.internal.process.PidUnavailableException;
    +import org.apache.geode.internal.process.ProcessStreamReader.InputListener;
    +import org.apache.geode.internal.process.ProcessType;
    +import org.apache.geode.internal.process.ProcessUtils;
    +import org.apache.geode.internal.process.lang.AvailablePid;
    +import org.apache.geode.internal.util.StopWatch;
    +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 {
    +  protected static final Logger logger = LogService.getLogger();
    +
    +  protected static final int WAIT_FOR_PROCESS_TO_DIE_TIMEOUT = 5 * 60 * 1000; // 5 minutes
    +  protected static final int TIMEOUT_MILLISECONDS = WAIT_FOR_PROCESS_TO_DIE_TIMEOUT;
    --- End diff --
    
    Unused field?


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] geode pull request #699: GEODE-3413: overhaul launcher and process classes a...

Posted by kirklund <gi...@git.apache.org>.
Github user kirklund commented on a diff in the pull request:

    https://github.com/apache/geode/pull/699#discussion_r132599627
  
    --- Diff: geode-core/src/main/java/org/apache/geode/internal/process/AttachProcessUtils.java ---
    @@ -14,21 +14,28 @@
      */
     package org.apache.geode.internal.process;
     
    -import org.apache.geode.internal.process.ProcessUtils.InternalProcessUtils;
    +import static org.apache.commons.lang.Validate.isTrue;
    +
     import com.sun.tools.attach.VirtualMachine;
     import com.sun.tools.attach.VirtualMachineDescriptor;
     
    +import org.apache.geode.internal.process.ProcessUtils.InternalProcessUtils;
    +
     /**
      * Implementation of the {@link ProcessUtils} SPI that uses the JDK Attach API.
      * 
      * @since GemFire 8.0
      */
     class AttachProcessUtils implements InternalProcessUtils {
     
    -  AttachProcessUtils() {}
    +  AttachProcessUtils() {
    --- End diff --
    
    Deleted ctor from AttachProcessUtils and NativeProcessUtils.


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] geode pull request #699: GEODE-3413: overhaul launcher and process classes a...

Posted by kirklund <gi...@git.apache.org>.
Github user kirklund commented on a diff in the pull request:

    https://github.com/apache/geode/pull/699#discussion_r132321751
  
    --- Diff: geode-core/src/test/java/org/apache/geode/distributed/ServerLauncherRemoteIntegrationTestCase.java ---
    @@ -0,0 +1,270 @@
    +/*
    + * 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.LOG_LEVEL;
    +import static org.apache.geode.distributed.ConfigurationProperties.MCAST_PORT;
    +import static org.apache.geode.distributed.internal.DistributionConfig.GEMFIRE_PREFIX;
    +import static org.apache.geode.internal.cache.AbstractCacheServer.TEST_OVERRIDE_DEFAULT_PORT_PROPERTY;
    +import static org.apache.geode.internal.process.ProcessUtils.isProcessAlive;
    +import static org.assertj.core.api.Assertions.assertThat;
    +
    +import java.io.File;
    +import java.io.IOException;
    +import java.io.UncheckedIOException;
    +import java.net.BindException;
    +import java.util.ArrayList;
    +import java.util.List;
    +import java.util.concurrent.atomic.AtomicBoolean;
    +
    +import org.junit.After;
    +import org.junit.Before;
    +
    +import org.apache.geode.distributed.AbstractLauncher.Status;
    +import org.apache.geode.internal.process.ProcessStreamReader;
    +import org.apache.geode.internal.process.ProcessStreamReader.InputListener;
    +
    +/**
    + * Abstract base class for integration tests of {@link ServerLauncher} as an application main in a
    + * forked JVM.
    + *
    + * @since GemFire 8.0
    + */
    +public abstract class ServerLauncherRemoteIntegrationTestCase
    +    extends ServerLauncherIntegrationTestCase implements UsesServerCommand {
    +
    +  private final AtomicBoolean threwBindException = new AtomicBoolean();
    +
    +  protected volatile Process process;
    +  protected volatile ProcessStreamReader processOutReader;
    +  protected volatile ProcessStreamReader processErrReader;
    +
    +  private ServerCommand serverCommand;
    +
    +  @Before
    +  public void setUp() throws Exception {
    +    serverCommand = new ServerCommand(this);
    +  }
    +
    +  @After
    +  public 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
    +  public List<String> getJvmArguments() {
    +    List<String> jvmArguments = new ArrayList<>();
    +    jvmArguments.add("-D" + GEMFIRE_PREFIX + LOG_LEVEL + "=config");
    +    jvmArguments.add("-D" + GEMFIRE_PREFIX + MCAST_PORT + "=0");
    +    jvmArguments
    +        .add("-D" + TEST_OVERRIDE_DEFAULT_PORT_PROPERTY + "=" + String.valueOf(defaultServerPort));
    +    return jvmArguments;
    +  }
    +
    +  @Override
    +  public String getName() {
    +    return getUniqueName();
    +  }
    +
    +  @Override
    +  public boolean getDisableDefaultServer() {
    +    return false;
    +  }
    +
    +  protected void assertThatServerThrewBindException() {
    +    assertThat(threwBindException.get()).isTrue();
    +  }
    +
    +  protected void assertThatServerThrew(final Class<? extends Throwable> throwableClass) {
    +    assertThat(threwBindException.get()).isTrue();
    +  }
    +
    +  protected ServerLauncher startServer(final ServerCommand command) {
    +    return awaitStart(command);
    +  }
    +
    +  protected ServerLauncher awaitStart(final ServerCommand command,
    +      final ProcessStreamReader.InputListener outListener,
    +      final ProcessStreamReader.InputListener errListener) throws Exception {
    +    executeCommandWithReaders(command.create(), outListener, errListener);
    +    ServerLauncher launcher = awaitStart(getWorkingDirectory());
    +    assertThat(process.isAlive()).isTrue();
    +    return launcher;
    +  }
    +
    +  protected ServerLauncher awaitStart(final ServerCommand command) {
    +    try {
    +      executeCommandWithReaders(command);
    +      ServerLauncher launcher = awaitStart(getWorkingDirectory());
    +      assertThat(process.isAlive()).isTrue();
    +      return launcher;
    +    } catch (IOException e) {
    +      throw new UncheckedIOException(e);
    +    }
    +  }
    +
    +  protected ServerLauncher awaitStart(final File workingDirectory) {
    +    try {
    +      this.launcher = new ServerLauncher.Builder()
    +          .setWorkingDirectory(workingDirectory.getCanonicalPath()).build();
    +      ServerLauncher launcher = awaitStart(this.launcher);
    +      assertThat(process.isAlive()).isTrue();
    +      return launcher;
    +    } catch (IOException e) {
    +      throw new UncheckedIOException(e);
    +    }
    +  }
    +
    +  @Override
    +  protected ServerLauncher awaitStart(final ServerLauncher launcher) {
    +    await().until(() -> assertThat(launcher.status().getStatus()).isEqualTo(Status.ONLINE));
    +    assertThat(process.isAlive()).isTrue();
    +    return launcher;
    +  }
    +
    +  protected ServerLauncher awaitStart() {
    +    return awaitStart(this.launcher);
    +  }
    +
    +  protected void awaitStop() {
    --- End diff --
    
    Delete unused method.


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] geode pull request #699: GEODE-3413: overhaul launcher and process classes a...

Posted by kirklund <gi...@git.apache.org>.
Github user kirklund commented on a diff in the pull request:

    https://github.com/apache/geode/pull/699#discussion_r132307026
  
    --- Diff: geode-core/src/test/java/org/apache/geode/distributed/AbstractLauncherTest.java ---
    @@ -14,253 +14,370 @@
      */
     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 isSetReturnsFalseIfPropertyHasRealValue() throws Exception {
    --- End diff --
    
    Nice catch!


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] geode issue #699: GEODE-3413: overhaul launcher and process classes and test...

Posted by kirklund <gi...@git.apache.org>.
Github user kirklund commented on the issue:

    https://github.com/apache/geode/pull/699
  
    These tests have also now been overhauled or rewritten:
    * LauncherMemberMXBeanIntegrationTest
    * ServerLauncherWaitOnServerMultiThreadedTest
    * ServerLauncherWithProviderIntegrationTest -> ServerLauncherWithProviderRegressionTest


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] geode pull request #699: GEODE-3413: overhaul launcher and process classes a...

Posted by pdxrunner <gi...@git.apache.org>.
Github user pdxrunner commented on a diff in the pull request:

    https://github.com/apache/geode/pull/699#discussion_r132285291
  
    --- Diff: geode-core/src/test/java/org/apache/geode/distributed/AbstractLauncherTest.java ---
    @@ -14,253 +14,370 @@
      */
     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 isSetReturnsFalseIfPropertyHasRealValue() throws Exception {
    --- End diff --
    
    Shouldn't this test name be 'isSetReturnsTrueIfPropertyHasRealValue'


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] geode issue #699: GEODE-3413: overhaul launcher and process classes and test...

Posted by kirklund <gi...@git.apache.org>.
Github user kirklund commented on the issue:

    https://github.com/apache/geode/pull/699
  
    Merged this PR to develop. Done!


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] geode pull request #699: GEODE-3413: overhaul launcher and process classes a...

Posted by kirklund <gi...@git.apache.org>.
Github user kirklund commented on a diff in the pull request:

    https://github.com/apache/geode/pull/699#discussion_r132324550
  
    --- Diff: geode-core/src/test/java/org/apache/geode/internal/process/lang/AvailablePidTest.java ---
    @@ -0,0 +1,74 @@
    +/*
    + * 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.internal.process.lang;
    --- End diff --
    
    Actually, just realized AvailablePid returns unused pids. Nothing in the javadoc or API says anything about it being "random" -- that's just how it's implemented. So the only really important details is that the pid is unused.


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] geode pull request #699: GEODE-3413: overhaul launcher and process classes a...

Posted by kirklund <gi...@git.apache.org>.
Github user kirklund commented on a diff in the pull request:

    https://github.com/apache/geode/pull/699#discussion_r132324608
  
    --- Diff: geode-core/src/test/java/org/apache/geode/internal/process/lang/AvailablePidTest.java ---
    @@ -0,0 +1,74 @@
    +/*
    + * 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.internal.process.lang;
    --- End diff --
    
    Oops there it is in the javadocs of the methods.


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] geode pull request #699: GEODE-3413: overhaul launcher and process classes a...

Posted by pdxrunner <gi...@git.apache.org>.
Github user pdxrunner commented on a diff in the pull request:

    https://github.com/apache/geode/pull/699#discussion_r132304059
  
    --- Diff: geode-core/src/test/java/org/apache/geode/internal/process/BlockingProcessStreamReaderIntegrationTest.java ---
    @@ -0,0 +1,179 @@
    +/*
    + * 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.internal.process;
    +
    +import static org.apache.geode.internal.lang.SystemUtils.isWindows;
    +import static org.apache.geode.internal.process.ProcessUtils.isProcessAlive;
    +import static org.assertj.core.api.Assertions.assertThat;
    +import static org.junit.Assume.assumeFalse;
    +
    +import org.junit.Before;
    +import org.junit.Test;
    +import org.junit.experimental.categories.Category;
    +
    +import org.apache.geode.internal.process.ProcessStreamReader.Builder;
    +import org.apache.geode.internal.process.ProcessStreamReader.ReadingMode;
    +import org.apache.geode.test.junit.categories.IntegrationTest;
    +
    +/**
    + * Functional integration tests for BlockingProcessStreamReader. All tests are skipped on Windows
    + * due to TRAC bug #51967 which is caused by a JDK bug. See
    --- End diff --
    
    See my other comment regarding specific bug reference.


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] geode pull request #699: GEODE-3413: overhaul launcher and process classes a...

Posted by kirklund <gi...@git.apache.org>.
Github user kirklund commented on a diff in the pull request:

    https://github.com/apache/geode/pull/699#discussion_r132533643
  
    --- Diff: geode-core/src/main/java/org/apache/geode/internal/cache/ClusterConfigurationLoader.java ---
    @@ -31,7 +31,7 @@
     import org.apache.geode.internal.admin.remote.DistributionLocatorId;
     import org.apache.geode.internal.i18n.LocalizedStrings;
     import org.apache.geode.internal.logging.LogService;
    -import org.apache.geode.internal.process.ClusterConfigurationNotAvailableException;
    +import org.apache.geode.config.internal.ClusterConfigurationNotAvailableException;
    --- End diff --
    
    Done.


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] geode pull request #699: GEODE-3413: overhaul launcher and process classes a...

Posted by kirklund <gi...@git.apache.org>.
Github user kirklund commented on a diff in the pull request:

    https://github.com/apache/geode/pull/699#discussion_r132321803
  
    --- Diff: geode-core/src/test/java/org/apache/geode/distributed/ServerLauncherRemoteIntegrationTestCase.java ---
    @@ -0,0 +1,270 @@
    +/*
    + * 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.LOG_LEVEL;
    +import static org.apache.geode.distributed.ConfigurationProperties.MCAST_PORT;
    +import static org.apache.geode.distributed.internal.DistributionConfig.GEMFIRE_PREFIX;
    +import static org.apache.geode.internal.cache.AbstractCacheServer.TEST_OVERRIDE_DEFAULT_PORT_PROPERTY;
    +import static org.apache.geode.internal.process.ProcessUtils.isProcessAlive;
    +import static org.assertj.core.api.Assertions.assertThat;
    +
    +import java.io.File;
    +import java.io.IOException;
    +import java.io.UncheckedIOException;
    +import java.net.BindException;
    +import java.util.ArrayList;
    +import java.util.List;
    +import java.util.concurrent.atomic.AtomicBoolean;
    +
    +import org.junit.After;
    +import org.junit.Before;
    +
    +import org.apache.geode.distributed.AbstractLauncher.Status;
    +import org.apache.geode.internal.process.ProcessStreamReader;
    +import org.apache.geode.internal.process.ProcessStreamReader.InputListener;
    +
    +/**
    + * Abstract base class for integration tests of {@link ServerLauncher} as an application main in a
    + * forked JVM.
    + *
    + * @since GemFire 8.0
    + */
    +public abstract class ServerLauncherRemoteIntegrationTestCase
    +    extends ServerLauncherIntegrationTestCase implements UsesServerCommand {
    +
    +  private final AtomicBoolean threwBindException = new AtomicBoolean();
    +
    +  protected volatile Process process;
    +  protected volatile ProcessStreamReader processOutReader;
    +  protected volatile ProcessStreamReader processErrReader;
    +
    +  private ServerCommand serverCommand;
    +
    +  @Before
    +  public void setUp() throws Exception {
    +    serverCommand = new ServerCommand(this);
    +  }
    +
    +  @After
    +  public 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
    +  public List<String> getJvmArguments() {
    +    List<String> jvmArguments = new ArrayList<>();
    +    jvmArguments.add("-D" + GEMFIRE_PREFIX + LOG_LEVEL + "=config");
    +    jvmArguments.add("-D" + GEMFIRE_PREFIX + MCAST_PORT + "=0");
    +    jvmArguments
    +        .add("-D" + TEST_OVERRIDE_DEFAULT_PORT_PROPERTY + "=" + String.valueOf(defaultServerPort));
    +    return jvmArguments;
    +  }
    +
    +  @Override
    +  public String getName() {
    +    return getUniqueName();
    +  }
    +
    +  @Override
    +  public boolean getDisableDefaultServer() {
    +    return false;
    +  }
    +
    +  protected void assertThatServerThrewBindException() {
    +    assertThat(threwBindException.get()).isTrue();
    +  }
    +
    +  protected void assertThatServerThrew(final Class<? extends Throwable> throwableClass) {
    +    assertThat(threwBindException.get()).isTrue();
    +  }
    +
    +  protected ServerLauncher startServer(final ServerCommand command) {
    +    return awaitStart(command);
    +  }
    +
    +  protected ServerLauncher awaitStart(final ServerCommand command,
    +      final ProcessStreamReader.InputListener outListener,
    +      final ProcessStreamReader.InputListener errListener) throws Exception {
    +    executeCommandWithReaders(command.create(), outListener, errListener);
    +    ServerLauncher launcher = awaitStart(getWorkingDirectory());
    +    assertThat(process.isAlive()).isTrue();
    +    return launcher;
    +  }
    +
    +  protected ServerLauncher awaitStart(final ServerCommand command) {
    +    try {
    +      executeCommandWithReaders(command);
    +      ServerLauncher launcher = awaitStart(getWorkingDirectory());
    +      assertThat(process.isAlive()).isTrue();
    +      return launcher;
    +    } catch (IOException e) {
    +      throw new UncheckedIOException(e);
    +    }
    +  }
    +
    +  protected ServerLauncher awaitStart(final File workingDirectory) {
    +    try {
    +      this.launcher = new ServerLauncher.Builder()
    +          .setWorkingDirectory(workingDirectory.getCanonicalPath()).build();
    +      ServerLauncher launcher = awaitStart(this.launcher);
    +      assertThat(process.isAlive()).isTrue();
    +      return launcher;
    +    } catch (IOException e) {
    +      throw new UncheckedIOException(e);
    +    }
    +  }
    +
    +  @Override
    +  protected ServerLauncher awaitStart(final ServerLauncher launcher) {
    +    await().until(() -> assertThat(launcher.status().getStatus()).isEqualTo(Status.ONLINE));
    +    assertThat(process.isAlive()).isTrue();
    +    return launcher;
    +  }
    +
    +  protected ServerLauncher awaitStart() {
    +    return awaitStart(this.launcher);
    +  }
    +
    +  protected void awaitStop() {
    +    await().until(() -> assertThat(this.process.isAlive()).isFalse());
    +  }
    +
    +  protected void assertStopOf(final Process process) {
    +    await().until(() -> assertThat(process.isAlive()).isFalse());
    +  }
    +
    +  protected Process getServerProcess() {
    +    return this.process;
    +  }
    +
    +  protected void startServerShouldFail(final ServerCommand command, final InputListener outListener,
    +      final InputListener errListener) throws IOException, InterruptedException {
    +    executeCommandWithReaders(command.create(), outListener, errListener);
    +    process.waitFor(2, MINUTES);
    +    assertThat(process.isAlive()).isFalse();
    +    assertThat(process.exitValue()).isEqualTo(1);
    +  }
    +
    +  protected void startServerShouldFail(final ServerCommand command)
    +      throws IOException, InterruptedException {
    +    startServerShouldFail(command, createBindExceptionListener("sysout", threwBindException),
    +        createBindExceptionListener("syserr", threwBindException));
    +  }
    +
    +  protected void startServerShouldFail() throws IOException, InterruptedException {
    +    startServerShouldFail(serverCommand);
    +  }
    +
    +  private InputListener createBindExceptionListener(final String name,
    +      final AtomicBoolean threwBindException) {
    +    return createExpectedListener(name, getUniqueName() + "#" + name, BindException.class.getName(),
    +        threwBindException);
    +  }
    +
    +  @Override
    +  protected ServerLauncher startServer() {
    +    return startServer(serverCommand);
    +  }
    +
    +  protected void assertThatProcessIsNotAlive() {
    +    assertThatProcessIsNotAlive(process);
    +  }
    +
    +  protected void assertThatProcessIsNotAlive(final Process process) {
    +    assertThat(process.isAlive()).isFalse();
    +  }
    +
    +  protected void assertProcessIsNotAlive() {
    --- End diff --
    
    Delete unused method.


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] geode pull request #699: GEODE-3413: overhaul launcher and process classes a...

Posted by kirklund <gi...@git.apache.org>.
Github user kirklund commented on a diff in the pull request:

    https://github.com/apache/geode/pull/699#discussion_r132542091
  
    --- Diff: geode-core/src/test/java/org/apache/geode/distributed/LauncherIntegrationTestCase.java ---
    @@ -0,0 +1,505 @@
    +/*
    + * 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.nio.file.Files;
    +import java.util.List;
    +import java.util.Properties;
    +import java.util.concurrent.Callable;
    +import java.util.concurrent.atomic.AtomicBoolean;
    +
    +import org.apache.commons.lang.StringUtils;
    +import org.apache.logging.log4j.Logger;
    +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.logging.LogService;
    +import org.apache.geode.internal.net.SocketCreatorFactory;
    +import org.apache.geode.internal.process.PidUnavailableException;
    +import org.apache.geode.internal.process.ProcessStreamReader.InputListener;
    +import org.apache.geode.internal.process.ProcessType;
    +import org.apache.geode.internal.process.ProcessUtils;
    +import org.apache.geode.internal.process.lang.AvailablePid;
    +import org.apache.geode.internal.util.StopWatch;
    +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 {
    +  protected static final Logger logger = LogService.getLogger();
    +
    +  protected static final int WAIT_FOR_PROCESS_TO_DIE_TIMEOUT = 5 * 60 * 1000; // 5 minutes
    +  protected static final int TIMEOUT_MILLISECONDS = WAIT_FOR_PROCESS_TO_DIE_TIMEOUT;
    +  protected static final int WAIT_FOR_FILE_CREATION_TIMEOUT = 10 * 1000; // 10s
    +  protected static final int WAIT_FOR_FILE_DELETION_TIMEOUT = 10 * 1000; // 10s
    +  protected static final int WAIT_FOR_MBEAN_TIMEOUT = 10 * 1000; // 10s
    --- End diff --
    
    All unused fields deleted.


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] geode pull request #699: GEODE-3413: overhaul launcher and process classes a...

Posted by pdxrunner <gi...@git.apache.org>.
Github user pdxrunner commented on a diff in the pull request:

    https://github.com/apache/geode/pull/699#discussion_r132281558
  
    --- Diff: geode-core/src/test/java/org/apache/geode/distributed/AbstractLauncherIntegrationTest.java ---
    @@ -47,26 +50,21 @@
     
       @Before
       public void setUp() throws Exception {
    -    this.gemfirePropertiesFile =
    -        this.temporaryFolder.newFile(DistributionConfig.GEMFIRE_PREFIX + "properties");
    +    propertiesFile = temporaryFolder.newFile(GEMFIRE_PREFIX + "properties");
     
    -    this.expectedGemfireProperties = new Properties();
    -    this.expectedGemfireProperties.setProperty(NAME, "memberOne");
    -    this.expectedGemfireProperties.setProperty(GROUPS, "groupOne, groupTwo");
    -    this.expectedGemfireProperties.store(new FileWriter(this.gemfirePropertiesFile, false),
    -        this.testName.getMethodName());
    +    expectedProperties = new Properties();
    +    expectedProperties.setProperty(NAME, "memberOne");
    +    expectedProperties.setProperty(GROUPS, "groupOne, groupTwo");
    +    expectedProperties.store(new FileWriter(propertiesFile, false), testName.getMethodName());
     
    -    assertThat(this.gemfirePropertiesFile).isNotNull();
    -    assertThat(this.gemfirePropertiesFile.exists()).isTrue();
    -    assertThat(this.gemfirePropertiesFile.isFile()).isTrue();
    +    assertThat(propertiesFile).exists().isFile();
       }
     
       @Test
    -  public void testLoadGemFirePropertiesFromFile() throws Exception {
    -    final Properties actualGemFireProperties =
    -        AbstractLauncher.loadGemFireProperties(this.gemfirePropertiesFile.toURI().toURL());
    +  public void loadGemFirePropertiesFromFile() throws Exception {
    +    Properties loadedProperties = loadGemFireProperties(propertiesFile.toURI().toURL());
     
    -    assertThat(actualGemFireProperties).isNotNull();
    -    assertThat(actualGemFireProperties).isEqualTo(this.expectedGemfireProperties);
    +    assertThat(loadedProperties).isEqualTo(expectedProperties);
       }
    +
    --- End diff --
    
    nit-pick: unnecessary blank line 


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] geode pull request #699: GEODE-3413: overhaul launcher and process classes a...

Posted by kirklund <gi...@git.apache.org>.
Github user kirklund commented on a diff in the pull request:

    https://github.com/apache/geode/pull/699#discussion_r132599333
  
    --- Diff: geode-core/src/main/java/org/apache/geode/distributed/LocatorLauncher.java ---
    @@ -1781,8 +1782,8 @@ protected void validate() {
          * @see org.apache.geode.distributed.LocatorLauncher.Command#START
          */
         protected void validateOnStart() {
    -      if (Command.START.equals(getCommand())) {
    -        if (StringUtils.isBlank(getMemberName())
    +      if (Command.START == getCommand()) {
    --- End diff --
    
    Yep, IntelliJ has an automated refactoring and inspection for this. I don't even remember making this change unless I was trying to make LocatorLauncher more consistent with ServerLauncher.


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] geode pull request #699: GEODE-3413: overhaul launcher and process classes a...

Posted by jaredjstewart <gi...@git.apache.org>.
Github user jaredjstewart commented on a diff in the pull request:

    https://github.com/apache/geode/pull/699#discussion_r132562988
  
    --- Diff: geode-core/src/main/java/org/apache/geode/distributed/AbstractLauncher.java ---
    @@ -795,25 +785,25 @@ protected String toString(final Date dateTime) {
     
         // the value of a Number as a String, or "" if null
         protected String toString(final Number value) {
    -      return StringUtils.defaultString(value);
    +      return defaultString(value);
         }
     
         // a String concatenation of all values separated by " "
         protected String toString(final Object... values) {
    -      return values == null ? "" : StringUtils.join(values, " ");
    +      return values == null ? "" : join(values, " ");
         }
     
         // the value of the String, or "" if value is null
         protected String toString(final String value) {
    -      return ObjectUtils.defaultIfNull(value, "");
    +      return defaultIfNull(value, "");
         }
       }
     
       /**
        * The Status enumerated type represents the various lifecycle states of a GemFire service (such
        * as a Cache Server, a Locator or a Manager).
        */
    -  public static enum Status {
    --- End diff --
    
    What is the motivation for removing static here?   I believe Effective Java advocates for favoring static member classes over non-static.


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] geode pull request #699: GEODE-3413: overhaul launcher and process classes a...

Posted by kirklund <gi...@git.apache.org>.
Github user kirklund commented on a diff in the pull request:

    https://github.com/apache/geode/pull/699#discussion_r132321846
  
    --- Diff: geode-core/src/test/java/org/apache/geode/distributed/ServerLauncherRemoteIntegrationTestCase.java ---
    @@ -0,0 +1,270 @@
    +/*
    + * 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.LOG_LEVEL;
    +import static org.apache.geode.distributed.ConfigurationProperties.MCAST_PORT;
    +import static org.apache.geode.distributed.internal.DistributionConfig.GEMFIRE_PREFIX;
    +import static org.apache.geode.internal.cache.AbstractCacheServer.TEST_OVERRIDE_DEFAULT_PORT_PROPERTY;
    +import static org.apache.geode.internal.process.ProcessUtils.isProcessAlive;
    +import static org.assertj.core.api.Assertions.assertThat;
    +
    +import java.io.File;
    +import java.io.IOException;
    +import java.io.UncheckedIOException;
    +import java.net.BindException;
    +import java.util.ArrayList;
    +import java.util.List;
    +import java.util.concurrent.atomic.AtomicBoolean;
    +
    +import org.junit.After;
    +import org.junit.Before;
    +
    +import org.apache.geode.distributed.AbstractLauncher.Status;
    +import org.apache.geode.internal.process.ProcessStreamReader;
    +import org.apache.geode.internal.process.ProcessStreamReader.InputListener;
    +
    +/**
    + * Abstract base class for integration tests of {@link ServerLauncher} as an application main in a
    + * forked JVM.
    + *
    + * @since GemFire 8.0
    + */
    +public abstract class ServerLauncherRemoteIntegrationTestCase
    +    extends ServerLauncherIntegrationTestCase implements UsesServerCommand {
    +
    +  private final AtomicBoolean threwBindException = new AtomicBoolean();
    +
    +  protected volatile Process process;
    +  protected volatile ProcessStreamReader processOutReader;
    +  protected volatile ProcessStreamReader processErrReader;
    +
    +  private ServerCommand serverCommand;
    +
    +  @Before
    +  public void setUp() throws Exception {
    +    serverCommand = new ServerCommand(this);
    +  }
    +
    +  @After
    +  public 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
    +  public List<String> getJvmArguments() {
    +    List<String> jvmArguments = new ArrayList<>();
    +    jvmArguments.add("-D" + GEMFIRE_PREFIX + LOG_LEVEL + "=config");
    +    jvmArguments.add("-D" + GEMFIRE_PREFIX + MCAST_PORT + "=0");
    +    jvmArguments
    +        .add("-D" + TEST_OVERRIDE_DEFAULT_PORT_PROPERTY + "=" + String.valueOf(defaultServerPort));
    +    return jvmArguments;
    +  }
    +
    +  @Override
    +  public String getName() {
    +    return getUniqueName();
    +  }
    +
    +  @Override
    +  public boolean getDisableDefaultServer() {
    +    return false;
    +  }
    +
    +  protected void assertThatServerThrewBindException() {
    +    assertThat(threwBindException.get()).isTrue();
    +  }
    +
    +  protected void assertThatServerThrew(final Class<? extends Throwable> throwableClass) {
    +    assertThat(threwBindException.get()).isTrue();
    +  }
    +
    +  protected ServerLauncher startServer(final ServerCommand command) {
    +    return awaitStart(command);
    +  }
    +
    +  protected ServerLauncher awaitStart(final ServerCommand command,
    +      final ProcessStreamReader.InputListener outListener,
    +      final ProcessStreamReader.InputListener errListener) throws Exception {
    +    executeCommandWithReaders(command.create(), outListener, errListener);
    +    ServerLauncher launcher = awaitStart(getWorkingDirectory());
    +    assertThat(process.isAlive()).isTrue();
    +    return launcher;
    +  }
    +
    +  protected ServerLauncher awaitStart(final ServerCommand command) {
    +    try {
    +      executeCommandWithReaders(command);
    +      ServerLauncher launcher = awaitStart(getWorkingDirectory());
    +      assertThat(process.isAlive()).isTrue();
    +      return launcher;
    +    } catch (IOException e) {
    +      throw new UncheckedIOException(e);
    +    }
    +  }
    +
    +  protected ServerLauncher awaitStart(final File workingDirectory) {
    +    try {
    +      this.launcher = new ServerLauncher.Builder()
    +          .setWorkingDirectory(workingDirectory.getCanonicalPath()).build();
    +      ServerLauncher launcher = awaitStart(this.launcher);
    +      assertThat(process.isAlive()).isTrue();
    +      return launcher;
    +    } catch (IOException e) {
    +      throw new UncheckedIOException(e);
    +    }
    +  }
    +
    +  @Override
    +  protected ServerLauncher awaitStart(final ServerLauncher launcher) {
    +    await().until(() -> assertThat(launcher.status().getStatus()).isEqualTo(Status.ONLINE));
    +    assertThat(process.isAlive()).isTrue();
    +    return launcher;
    +  }
    +
    +  protected ServerLauncher awaitStart() {
    +    return awaitStart(this.launcher);
    +  }
    +
    +  protected void awaitStop() {
    +    await().until(() -> assertThat(this.process.isAlive()).isFalse());
    +  }
    +
    +  protected void assertStopOf(final Process process) {
    +    await().until(() -> assertThat(process.isAlive()).isFalse());
    +  }
    +
    +  protected Process getServerProcess() {
    +    return this.process;
    +  }
    +
    +  protected void startServerShouldFail(final ServerCommand command, final InputListener outListener,
    +      final InputListener errListener) throws IOException, InterruptedException {
    +    executeCommandWithReaders(command.create(), outListener, errListener);
    +    process.waitFor(2, MINUTES);
    +    assertThat(process.isAlive()).isFalse();
    +    assertThat(process.exitValue()).isEqualTo(1);
    +  }
    +
    +  protected void startServerShouldFail(final ServerCommand command)
    +      throws IOException, InterruptedException {
    +    startServerShouldFail(command, createBindExceptionListener("sysout", threwBindException),
    +        createBindExceptionListener("syserr", threwBindException));
    +  }
    +
    +  protected void startServerShouldFail() throws IOException, InterruptedException {
    +    startServerShouldFail(serverCommand);
    +  }
    +
    +  private InputListener createBindExceptionListener(final String name,
    +      final AtomicBoolean threwBindException) {
    +    return createExpectedListener(name, getUniqueName() + "#" + name, BindException.class.getName(),
    +        threwBindException);
    +  }
    +
    +  @Override
    +  protected ServerLauncher startServer() {
    +    return startServer(serverCommand);
    +  }
    +
    +  protected void assertThatProcessIsNotAlive() {
    +    assertThatProcessIsNotAlive(process);
    +  }
    +
    +  protected void assertThatProcessIsNotAlive(final Process process) {
    +    assertThat(process.isAlive()).isFalse();
    +  }
    +
    +  protected void assertProcessIsNotAlive() {
    +    assertThat(process.isAlive()).isFalse();
    +  }
    +
    +  protected void assertProcessIsAlive() {
    --- End diff --
    
    Delete unused method. Etc. I'm not gonna mark the rest of these... just delete them if they're unused.


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] geode pull request #699: GEODE-3413: overhaul launcher and process classes a...

Posted by kirklund <gi...@git.apache.org>.
Github user kirklund commented on a diff in the pull request:

    https://github.com/apache/geode/pull/699#discussion_r132541957
  
    --- Diff: geode-core/src/main/java/org/apache/geode/distributed/LocatorLauncher.java ---
    @@ -1848,8 +1884,7 @@ public LocatorLauncher build() {
         private final String name;
     
         Command(final String name, final String... options) {
    -      assert !StringUtils
    -          .isBlank(name) : "The name of the locator launcher command must be specified!";
    +      assert !isBlank(name) : "The name of the locator launcher command must be specified!";
    --- End diff --
    
    Changed.


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] geode pull request #699: GEODE-3413: overhaul launcher and process classes a...

Posted by kirklund <gi...@git.apache.org>.
Github user kirklund commented on a diff in the pull request:

    https://github.com/apache/geode/pull/699#discussion_r132542106
  
    --- Diff: geode-core/src/test/java/org/apache/geode/distributed/LauncherIntegrationTestCase.java ---
    @@ -0,0 +1,505 @@
    +/*
    + * 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.nio.file.Files;
    +import java.util.List;
    +import java.util.Properties;
    +import java.util.concurrent.Callable;
    +import java.util.concurrent.atomic.AtomicBoolean;
    +
    +import org.apache.commons.lang.StringUtils;
    +import org.apache.logging.log4j.Logger;
    +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.logging.LogService;
    +import org.apache.geode.internal.net.SocketCreatorFactory;
    +import org.apache.geode.internal.process.PidUnavailableException;
    +import org.apache.geode.internal.process.ProcessStreamReader.InputListener;
    +import org.apache.geode.internal.process.ProcessType;
    +import org.apache.geode.internal.process.ProcessUtils;
    +import org.apache.geode.internal.process.lang.AvailablePid;
    +import org.apache.geode.internal.util.StopWatch;
    +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 {
    +  protected static final Logger logger = LogService.getLogger();
    +
    +  protected static final int WAIT_FOR_PROCESS_TO_DIE_TIMEOUT = 5 * 60 * 1000; // 5 minutes
    +  protected static final int TIMEOUT_MILLISECONDS = WAIT_FOR_PROCESS_TO_DIE_TIMEOUT;
    +  protected static final int WAIT_FOR_FILE_CREATION_TIMEOUT = 10 * 1000; // 10s
    +  protected static final int WAIT_FOR_FILE_DELETION_TIMEOUT = 10 * 1000; // 10s
    +  protected static final int WAIT_FOR_MBEAN_TIMEOUT = 10 * 1000; // 10s
    +  protected static final int INTERVAL_MILLISECONDS = 100;
    +
    +  protected static final int PREFERRED_FAKE_PID = 42;
    +
    +  private static final String EXPECTED_EXCEPTION_ADD =
    +      "<ExpectedException action=add>{}</ExpectedException>";
    +  private static final String EXPECTED_EXCEPTION_REMOVE =
    --- End diff --
    
    All unused fields deleted.


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] geode pull request #699: GEODE-3413: overhaul launcher and process classes a...

Posted by kirklund <gi...@git.apache.org>.
Github user kirklund commented on a diff in the pull request:

    https://github.com/apache/geode/pull/699#discussion_r132600143
  
    --- Diff: geode-core/src/main/java/org/apache/geode/internal/process/LocalProcessLauncher.java ---
    @@ -96,33 +117,55 @@ void close() {
        * @throws IOException if unable to create or write to the file
        */
       private void writePid(final boolean force) throws FileAlreadyExistsException, IOException {
    -    final boolean created = this.pidFile.createNewFile();
    -    if (!created && !force) {
    -      int otherPid = 0;
    -      try {
    -        otherPid = ProcessUtils.readPid(this.pidFile);
    -      } catch (IOException e) {
    -        // suppress
    -      } catch (NumberFormatException e) {
    -        // suppress
    -      }
    -      boolean ignorePidFile = false;
    -      if (otherPid != 0 && !ignoreIsPidAlive()) {
    -        ignorePidFile = !ProcessUtils.isProcessAlive(otherPid);
    -      }
    -      if (!ignorePidFile) {
    -        throw new FileAlreadyExistsException("Pid file already exists: " + this.pidFile + " for "
    -            + (otherPid > 0 ? "process " + otherPid : "unknown process"));
    +    if (this.pidFile.exists()) {
    +      if (!force) {
    +        checkOtherPid(readOtherPid());
           }
    +      this.pidFile.delete();
    +    }
    +
    +    assert !this.pidFile.exists();
    --- End diff --
    
    I deleted them.


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] geode pull request #699: GEODE-3413: overhaul launcher and process classes a...

Posted by kirklund <gi...@git.apache.org>.
Github user kirklund commented on a diff in the pull request:

    https://github.com/apache/geode/pull/699#discussion_r132323674
  
    --- Diff: geode-core/src/test/java/org/apache/geode/internal/process/lang/AvailablePidTest.java ---
    @@ -0,0 +1,74 @@
    +/*
    + * 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.internal.process.lang;
    --- End diff --
    
    I'm not sure how to test this. For example, my first idea is to invoke it twice and make sure they're not the same but I don't think that's a safe assertion. It's also probably not safe to assert that they're not sequential. Hmm...


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] geode pull request #699: GEODE-3413: overhaul launcher and process classes a...

Posted by kirklund <gi...@git.apache.org>.
Github user kirklund commented on a diff in the pull request:

    https://github.com/apache/geode/pull/699#discussion_r132542169
  
    --- Diff: geode-core/src/test/java/org/apache/geode/distributed/ServerLauncherRemoteIntegrationTestCase.java ---
    @@ -0,0 +1,270 @@
    +/*
    + * 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.LOG_LEVEL;
    +import static org.apache.geode.distributed.ConfigurationProperties.MCAST_PORT;
    +import static org.apache.geode.distributed.internal.DistributionConfig.GEMFIRE_PREFIX;
    +import static org.apache.geode.internal.cache.AbstractCacheServer.TEST_OVERRIDE_DEFAULT_PORT_PROPERTY;
    +import static org.apache.geode.internal.process.ProcessUtils.isProcessAlive;
    +import static org.assertj.core.api.Assertions.assertThat;
    +
    +import java.io.File;
    +import java.io.IOException;
    +import java.io.UncheckedIOException;
    +import java.net.BindException;
    +import java.util.ArrayList;
    +import java.util.List;
    +import java.util.concurrent.atomic.AtomicBoolean;
    +
    +import org.junit.After;
    +import org.junit.Before;
    +
    +import org.apache.geode.distributed.AbstractLauncher.Status;
    +import org.apache.geode.internal.process.ProcessStreamReader;
    +import org.apache.geode.internal.process.ProcessStreamReader.InputListener;
    +
    +/**
    + * Abstract base class for integration tests of {@link ServerLauncher} as an application main in a
    + * forked JVM.
    + *
    + * @since GemFire 8.0
    + */
    +public abstract class ServerLauncherRemoteIntegrationTestCase
    +    extends ServerLauncherIntegrationTestCase implements UsesServerCommand {
    +
    +  private final AtomicBoolean threwBindException = new AtomicBoolean();
    +
    +  protected volatile Process process;
    +  protected volatile ProcessStreamReader processOutReader;
    +  protected volatile ProcessStreamReader processErrReader;
    +
    +  private ServerCommand serverCommand;
    +
    +  @Before
    +  public void setUp() throws Exception {
    +    serverCommand = new ServerCommand(this);
    +  }
    +
    +  @After
    +  public 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
    +  public List<String> getJvmArguments() {
    +    List<String> jvmArguments = new ArrayList<>();
    +    jvmArguments.add("-D" + GEMFIRE_PREFIX + LOG_LEVEL + "=config");
    +    jvmArguments.add("-D" + GEMFIRE_PREFIX + MCAST_PORT + "=0");
    +    jvmArguments
    +        .add("-D" + TEST_OVERRIDE_DEFAULT_PORT_PROPERTY + "=" + String.valueOf(defaultServerPort));
    +    return jvmArguments;
    +  }
    +
    +  @Override
    +  public String getName() {
    +    return getUniqueName();
    +  }
    +
    +  @Override
    +  public boolean getDisableDefaultServer() {
    +    return false;
    +  }
    +
    +  protected void assertThatServerThrewBindException() {
    +    assertThat(threwBindException.get()).isTrue();
    +  }
    +
    +  protected void assertThatServerThrew(final Class<? extends Throwable> throwableClass) {
    +    assertThat(threwBindException.get()).isTrue();
    +  }
    +
    +  protected ServerLauncher startServer(final ServerCommand command) {
    +    return awaitStart(command);
    +  }
    +
    +  protected ServerLauncher awaitStart(final ServerCommand command,
    +      final ProcessStreamReader.InputListener outListener,
    +      final ProcessStreamReader.InputListener errListener) throws Exception {
    +    executeCommandWithReaders(command.create(), outListener, errListener);
    +    ServerLauncher launcher = awaitStart(getWorkingDirectory());
    +    assertThat(process.isAlive()).isTrue();
    +    return launcher;
    +  }
    +
    +  protected ServerLauncher awaitStart(final ServerCommand command) {
    +    try {
    +      executeCommandWithReaders(command);
    +      ServerLauncher launcher = awaitStart(getWorkingDirectory());
    +      assertThat(process.isAlive()).isTrue();
    +      return launcher;
    +    } catch (IOException e) {
    +      throw new UncheckedIOException(e);
    +    }
    +  }
    +
    +  protected ServerLauncher awaitStart(final File workingDirectory) {
    +    try {
    +      this.launcher = new ServerLauncher.Builder()
    +          .setWorkingDirectory(workingDirectory.getCanonicalPath()).build();
    +      ServerLauncher launcher = awaitStart(this.launcher);
    +      assertThat(process.isAlive()).isTrue();
    +      return launcher;
    +    } catch (IOException e) {
    +      throw new UncheckedIOException(e);
    +    }
    +  }
    +
    +  @Override
    +  protected ServerLauncher awaitStart(final ServerLauncher launcher) {
    +    await().until(() -> assertThat(launcher.status().getStatus()).isEqualTo(Status.ONLINE));
    +    assertThat(process.isAlive()).isTrue();
    +    return launcher;
    +  }
    +
    +  protected ServerLauncher awaitStart() {
    +    return awaitStart(this.launcher);
    +  }
    +
    +  protected void awaitStop() {
    +    await().until(() -> assertThat(this.process.isAlive()).isFalse());
    +  }
    +
    +  protected void assertStopOf(final Process process) {
    +    await().until(() -> assertThat(process.isAlive()).isFalse());
    +  }
    +
    +  protected Process getServerProcess() {
    +    return this.process;
    +  }
    +
    +  protected void startServerShouldFail(final ServerCommand command, final InputListener outListener,
    +      final InputListener errListener) throws IOException, InterruptedException {
    +    executeCommandWithReaders(command.create(), outListener, errListener);
    +    process.waitFor(2, MINUTES);
    +    assertThat(process.isAlive()).isFalse();
    +    assertThat(process.exitValue()).isEqualTo(1);
    +  }
    +
    +  protected void startServerShouldFail(final ServerCommand command)
    +      throws IOException, InterruptedException {
    +    startServerShouldFail(command, createBindExceptionListener("sysout", threwBindException),
    +        createBindExceptionListener("syserr", threwBindException));
    +  }
    +
    +  protected void startServerShouldFail() throws IOException, InterruptedException {
    +    startServerShouldFail(serverCommand);
    +  }
    +
    +  private InputListener createBindExceptionListener(final String name,
    +      final AtomicBoolean threwBindException) {
    +    return createExpectedListener(name, getUniqueName() + "#" + name, BindException.class.getName(),
    +        threwBindException);
    +  }
    +
    +  @Override
    +  protected ServerLauncher startServer() {
    +    return startServer(serverCommand);
    +  }
    +
    +  protected void assertThatProcessIsNotAlive() {
    --- End diff --
    
    All unused methods deleted.


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] geode pull request #699: GEODE-3413: overhaul launcher and process classes a...

Posted by kirklund <gi...@git.apache.org>.
Github user kirklund commented on a diff in the pull request:

    https://github.com/apache/geode/pull/699#discussion_r132542063
  
    --- Diff: geode-core/src/test/java/org/apache/geode/distributed/LauncherIntegrationTestCase.java ---
    @@ -0,0 +1,505 @@
    +/*
    + * 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.nio.file.Files;
    +import java.util.List;
    +import java.util.Properties;
    +import java.util.concurrent.Callable;
    +import java.util.concurrent.atomic.AtomicBoolean;
    +
    +import org.apache.commons.lang.StringUtils;
    +import org.apache.logging.log4j.Logger;
    +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.logging.LogService;
    +import org.apache.geode.internal.net.SocketCreatorFactory;
    +import org.apache.geode.internal.process.PidUnavailableException;
    +import org.apache.geode.internal.process.ProcessStreamReader.InputListener;
    +import org.apache.geode.internal.process.ProcessType;
    +import org.apache.geode.internal.process.ProcessUtils;
    +import org.apache.geode.internal.process.lang.AvailablePid;
    +import org.apache.geode.internal.util.StopWatch;
    +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 {
    +  protected static final Logger logger = LogService.getLogger();
    +
    +  protected static final int WAIT_FOR_PROCESS_TO_DIE_TIMEOUT = 5 * 60 * 1000; // 5 minutes
    +  protected static final int TIMEOUT_MILLISECONDS = WAIT_FOR_PROCESS_TO_DIE_TIMEOUT;
    --- End diff --
    
    All unused fields deleted.


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] geode pull request #699: GEODE-3413: overhaul launcher and process classes a...

Posted by kirklund <gi...@git.apache.org>.
Github user kirklund commented on a diff in the pull request:

    https://github.com/apache/geode/pull/699#discussion_r132542146
  
    --- Diff: geode-core/src/test/java/org/apache/geode/distributed/LauncherIntegrationTestCase.java ---
    @@ -0,0 +1,505 @@
    +/*
    + * 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.nio.file.Files;
    +import java.util.List;
    +import java.util.Properties;
    +import java.util.concurrent.Callable;
    +import java.util.concurrent.atomic.AtomicBoolean;
    +
    +import org.apache.commons.lang.StringUtils;
    +import org.apache.logging.log4j.Logger;
    +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.logging.LogService;
    +import org.apache.geode.internal.net.SocketCreatorFactory;
    +import org.apache.geode.internal.process.PidUnavailableException;
    +import org.apache.geode.internal.process.ProcessStreamReader.InputListener;
    +import org.apache.geode.internal.process.ProcessType;
    +import org.apache.geode.internal.process.ProcessUtils;
    +import org.apache.geode.internal.process.lang.AvailablePid;
    +import org.apache.geode.internal.util.StopWatch;
    +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 {
    +  protected static final Logger logger = LogService.getLogger();
    +
    +  protected static final int WAIT_FOR_PROCESS_TO_DIE_TIMEOUT = 5 * 60 * 1000; // 5 minutes
    +  protected static final int TIMEOUT_MILLISECONDS = WAIT_FOR_PROCESS_TO_DIE_TIMEOUT;
    +  protected static final int WAIT_FOR_FILE_CREATION_TIMEOUT = 10 * 1000; // 10s
    +  protected static final int WAIT_FOR_FILE_DELETION_TIMEOUT = 10 * 1000; // 10s
    +  protected static final int WAIT_FOR_MBEAN_TIMEOUT = 10 * 1000; // 10s
    +  protected static final int INTERVAL_MILLISECONDS = 100;
    +
    +  protected static final int PREFERRED_FAKE_PID = 42;
    +
    +  private static final String EXPECTED_EXCEPTION_ADD =
    +      "<ExpectedException action=add>{}</ExpectedException>";
    +  private static final String EXPECTED_EXCEPTION_REMOVE =
    +      "<ExpectedException action=remove>{}</ExpectedException>";
    +  private static final String EXPECTED_EXCEPTION_MBEAN_NOT_REGISTERED =
    +      "MBean Not Registered In GemFire Domain";
    +
    +  private IgnoredException ignoredException;
    +
    +  protected int localPid;
    +  protected int fakePid;
    +
    +  protected volatile ServerSocket socket;
    +
    +  protected volatile File pidFile;
    +  protected volatile File stopRequestFile;
    +  protected volatile File statusRequestFile;
    +  protected volatile File statusFile;
    +
    +  @Rule
    +  public TestName testName = new TestName();
    +
    +  @Rule
    +  public RestoreSystemProperties restoreSystemProperties = new RestoreSystemProperties();
    +
    +  @Rule
    +  public TemporaryFolder temporaryFolder = new TemporaryFolder();
    +
    +  @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 (this.socket != null) {
    +      this.socket.close();
    +      this.socket = null;
    +    }
    +    delete(this.pidFile);
    +    delete(this.stopRequestFile);
    +    delete(this.statusRequestFile);
    +    delete(this.statusFile);
    +  }
    +
    +  protected abstract ProcessType getProcessType();
    +
    +  protected String getStopRequestFileName() {
    +    return getProcessType().getStopRequestFileName();
    +  }
    +
    +  protected String getStatusRequestFileName() {
    +    return getProcessType().getStatusRequestFileName();
    +  }
    +
    +  protected String getStatusFileName() {
    +    return getProcessType().getStatusFileName();
    +  }
    +
    +  protected void givenEmptyWorkingDirectory() {
    +    assertThat(getWorkingDirectory().listFiles()).hasSize(0);
    +  }
    +
    +  protected List<String> getJvmArguments() {
    +    return ManagementFactory.getRuntimeMXBean().getInputArguments();
    +  }
    +
    +  protected ConditionFactory await() {
    +    return Awaitility.await().atMost(2, MINUTES);
    +  }
    +
    +  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 File getPidFile() {
    +    return new File(getWorkingDirectory(), getProcessType().getPidFileName());
    +  }
    +
    +  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 getWorkingDirectory() {
    +    return this.temporaryFolder.getRoot();
    +  }
    +
    +  protected String getWorkingDirectoryPath() {
    +    try {
    +      return getWorkingDirectory().getCanonicalPath();
    +    } catch (IOException e) {
    +      throw new UncheckedIOException(e);
    +    }
    +  }
    +
    +  protected void createPidFile(final Object content) {
    --- End diff --
    
    All unused methods deleted.


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] geode pull request #699: GEODE-3413: overhaul launcher and process classes a...

Posted by kirklund <gi...@git.apache.org>.
Github user kirklund commented on a diff in the pull request:

    https://github.com/apache/geode/pull/699#discussion_r132312206
  
    --- Diff: geode-core/src/test/java/org/apache/geode/internal/process/FileProcessControllerIntegrationTest.java ---
    @@ -0,0 +1,243 @@
    +/*
    + * 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.internal.process;
    +
    +import static com.googlecode.catchexception.CatchException.caughtException;
    +import static com.googlecode.catchexception.CatchException.verifyException;
    +import static java.util.concurrent.TimeUnit.MILLISECONDS;
    +import static java.util.concurrent.TimeUnit.MINUTES;
    +import static org.assertj.core.api.Assertions.assertThat;
    +import static org.assertj.core.api.Assertions.assertThatThrownBy;
    +import static org.mockito.Mockito.mock;
    +import static org.mockito.Mockito.when;
    +
    +import java.io.File;
    +import java.util.concurrent.ExecutorService;
    +import java.util.concurrent.Executors;
    +import java.util.concurrent.TimeoutException;
    +import java.util.concurrent.atomic.AtomicReference;
    +
    +import org.awaitility.Awaitility;
    +import org.awaitility.core.ConditionFactory;
    +import org.junit.After;
    +import org.junit.Before;
    +import org.junit.Ignore;
    +import org.junit.Rule;
    +import org.junit.Test;
    +import org.junit.experimental.categories.Category;
    +import org.junit.rules.ErrorCollector;
    +import org.junit.rules.TemporaryFolder;
    +import org.junit.rules.TestName;
    +
    +import org.apache.geode.distributed.AbstractLauncher.Status;
    +import org.apache.geode.distributed.LocatorLauncher;
    +import org.apache.geode.distributed.LocatorLauncher.Builder;
    +import org.apache.geode.distributed.LocatorLauncher.LocatorState;
    +import org.apache.geode.internal.process.io.EmptyFileWriter;
    +import org.apache.geode.internal.process.io.IntegerFileWriter;
    +import org.apache.geode.internal.process.io.StringFileWriter;
    +import org.apache.geode.test.junit.categories.IntegrationTest;
    +
    +/**
    + * Integration tests for {@link FileProcessController}.
    + */
    +@Category(IntegrationTest.class)
    +public class FileProcessControllerIntegrationTest {
    +
    +  private static final String STATUS_JSON = generateStatusJson();
    +
    +  private final AtomicReference<String> statusRef = new AtomicReference<>();
    +
    +  private File pidFile;
    +  private File statusFile;
    +  private File statusRequestFile;
    +  private File stopRequestFile;
    +  private int pid;
    +  private FileControllerParameters params;
    +  private ExecutorService executor;
    +
    +  @Rule
    +  public ErrorCollector errorCollector = new ErrorCollector();
    +
    +  @Rule
    +  public TemporaryFolder temporaryFolder = new TemporaryFolder();
    +
    +  @Rule
    +  public TestName testName = new TestName();
    +
    +  @Before
    +  public void setUp() throws Exception {
    +    ProcessType processType = ProcessType.LOCATOR;
    +    File directory = temporaryFolder.getRoot();
    +    pidFile = new File(directory, processType.getPidFileName());
    +    statusFile = new File(directory, processType.getStatusFileName());
    +    statusRequestFile = new File(directory, processType.getStatusRequestFileName());
    +    stopRequestFile = new File(directory, processType.getStopRequestFileName());
    +    pid = ProcessUtils.identifyPid();
    +
    +    params = mock(FileControllerParameters.class);
    +    when(params.getPidFile()).thenReturn(pidFile);
    +    when(params.getProcessId()).thenReturn(pid);
    +    when(params.getProcessType()).thenReturn(processType);
    +    when(params.getDirectory()).thenReturn(temporaryFolder.getRoot());
    +
    +    executor = Executors.newSingleThreadExecutor();
    +  }
    +
    +  @After
    +  public void tearDown() throws Exception {
    +    assertThat(executor.shutdownNow()).isEmpty();
    +  }
    +
    +  @Test
    +  public void statusShouldAwaitTimeoutWhileFileIsEmpty() throws Exception {
    +    // given: FileProcessController with empty pidFile
    +    FileProcessController controller = new FileProcessController(params, pid, 10, MILLISECONDS);
    +
    +    // when:
    +    verifyException(controller).status();
    +
    +    // then: we expect TimeoutException to be thrown
    +    assertThat((Exception) caughtException()).isInstanceOf(TimeoutException.class)
    +        .hasMessageContaining("Timed out waiting for process to create").hasNoCause();
    +  }
    +
    +  @Test
    +  public void statusShouldReturnJsonFromStatusFile() throws Exception {
    +    // given: FileProcessController with pidFile containing real pid
    +    new IntegerFileWriter(pidFile).writeToFile(pid);
    +    FileProcessController controller = new FileProcessController(params, pid, 2, MINUTES);
    +
    +    // when: status is called in one thread
    +    executor.execute(() -> {
    +      try {
    +        statusRef.set(controller.status());
    +      } catch (Exception e) {
    +        errorCollector.addError(e);
    +      }
    +    });
    +
    +    // and: json is written to the status file
    +    new StringFileWriter(statusFile).writeToFile(STATUS_JSON);
    +
    +    // then: returned status should be the json in the file
    +    await().until(() -> assertThat(statusRef.get()).isEqualTo(STATUS_JSON));
    +  }
    +
    +  @Ignore // GEODE-3278
    --- End diff --
    
    This test has a few interesting things including the @Ignore for GEODE-3278 that warrant more documentation.


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] geode pull request #699: GEODE-3413: overhaul launcher and process classes a...

Posted by pdxrunner <gi...@git.apache.org>.
Github user pdxrunner commented on a diff in the pull request:

    https://github.com/apache/geode/pull/699#discussion_r132520010
  
    --- Diff: geode-core/src/main/java/org/apache/geode/internal/process/StartupStatus.java ---
    @@ -14,29 +14,37 @@
      */
     package org.apache.geode.internal.process;
     
    +import static org.apache.commons.lang.Validate.notNull;
    +
     import org.apache.logging.log4j.Logger;
     
    -import org.apache.geode.internal.logging.LogService;
     import org.apache.geode.i18n.StringId;
    +import org.apache.geode.internal.logging.LogService;
     
     /**
      * Extracted from LogWriterImpl and changed to static.
    - * 
      */
    --- End diff --
    
    Is this javadoc necessary?


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] geode pull request #699: GEODE-3413: overhaul launcher and process classes a...

Posted by kirklund <gi...@git.apache.org>.
Github user kirklund closed the pull request at:

    https://github.com/apache/geode/pull/699


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] geode pull request #699: GEODE-3413: overhaul launcher and process classes a...

Posted by kirklund <gi...@git.apache.org>.
Github user kirklund commented on a diff in the pull request:

    https://github.com/apache/geode/pull/699#discussion_r132541592
  
    --- Diff: geode-core/src/main/java/org/apache/geode/distributed/AbstractLauncher.java ---
    @@ -502,7 +507,7 @@ protected static Integer identifyPid() {
           }
         }
     
    -    // TODO refactor the logic in this method into a DateTimeFormatUtils class
    +    // consider refactoring the logic in this method into a DateTimeFormatUtils class
    --- End diff --
    
    Deleted.


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] geode pull request #699: GEODE-3413: overhaul launcher and process classes a...

Posted by kirklund <gi...@git.apache.org>.
Github user kirklund commented on a diff in the pull request:

    https://github.com/apache/geode/pull/699#discussion_r132542008
  
    --- Diff: geode-core/src/test/java/org/apache/geode/internal/process/BlockingProcessStreamReaderWindowsTest.java ---
    @@ -0,0 +1,97 @@
    +/*
    + * 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.internal.process;
    +
    +import static org.apache.geode.internal.lang.SystemUtils.isWindows;
    +import static org.assertj.core.api.Assertions.assertThat;
    +import static org.assertj.core.api.Assertions.assertThatThrownBy;
    +import static org.junit.Assume.assumeTrue;
    +
    +import java.util.concurrent.ExecutorService;
    +import java.util.concurrent.Executors;
    +import java.util.concurrent.Future;
    +import java.util.concurrent.TimeUnit;
    +import java.util.concurrent.TimeoutException;
    +
    +import org.junit.After;
    +import org.junit.Before;
    +import org.junit.Test;
    +import org.junit.experimental.categories.Category;
    +
    +import org.apache.geode.test.junit.categories.IntegrationTest;
    +
    +/**
    + * Functional integration test {@link #hangsOnWindows} for BlockingProcessStreamReader which
    + * verifies TRAC #51967 on Windows. The hang is caused by a JDK bug in which a thread invoking
    --- End diff --
    
    I added description.


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] geode pull request #699: GEODE-3413: overhaul launcher and process classes a...

Posted by kirklund <gi...@git.apache.org>.
Github user kirklund commented on a diff in the pull request:

    https://github.com/apache/geode/pull/699#discussion_r132598795
  
    --- Diff: geode-core/src/main/java/org/apache/geode/distributed/AbstractLauncher.java ---
    @@ -795,25 +785,25 @@ protected String toString(final Date dateTime) {
     
         // the value of a Number as a String, or "" if null
         protected String toString(final Number value) {
    -      return StringUtils.defaultString(value);
    +      return defaultString(value);
         }
     
         // a String concatenation of all values separated by " "
         protected String toString(final Object... values) {
    -      return values == null ? "" : StringUtils.join(values, " ");
    +      return values == null ? "" : join(values, " ");
         }
     
         // the value of the String, or "" if value is null
         protected String toString(final String value) {
    -      return ObjectUtils.defaultIfNull(value, "");
    +      return defaultIfNull(value, "");
         }
       }
     
       /**
        * The Status enumerated type represents the various lifecycle states of a GemFire service (such
        * as a Cache Server, a Locator or a Manager).
        */
    -  public static enum Status {
    --- End diff --
    
    It's static with or without the keyword. IntelliJ grays it out so I just deleted it. Similar to public on methods defined in an Interface.


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] geode pull request #699: GEODE-3413: overhaul launcher and process classes a...

Posted by kirklund <gi...@git.apache.org>.
Github user kirklund commented on a diff in the pull request:

    https://github.com/apache/geode/pull/699#discussion_r132308040
  
    --- Diff: geode-core/src/test/java/org/apache/geode/distributed/AbstractLauncherTest.java ---
    @@ -14,253 +14,370 @@
      */
     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, "");
    --- End diff --
    
    Done! I made this change in all launcher and process main classes and test classes.


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] geode pull request #699: GEODE-3413: overhaul launcher and process classes a...

Posted by kirklund <gi...@git.apache.org>.
Github user kirklund commented on a diff in the pull request:

    https://github.com/apache/geode/pull/699#discussion_r132532612
  
    --- Diff: geode-core/src/main/java/org/apache/geode/config/internal/ClusterConfigurationNotAvailableException.java ---
    @@ -0,0 +1,29 @@
    +/*
    + * 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.config.internal;
    --- End diff --
    
    Changed.


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] geode pull request #699: GEODE-3413: overhaul launcher and process classes a...

Posted by pdxrunner <gi...@git.apache.org>.
Github user pdxrunner commented on a diff in the pull request:

    https://github.com/apache/geode/pull/699#discussion_r132314371
  
    --- Diff: geode-core/src/test/java/org/apache/geode/distributed/LauncherIntegrationTestCase.java ---
    @@ -0,0 +1,505 @@
    +/*
    + * 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.nio.file.Files;
    +import java.util.List;
    +import java.util.Properties;
    +import java.util.concurrent.Callable;
    +import java.util.concurrent.atomic.AtomicBoolean;
    +
    +import org.apache.commons.lang.StringUtils;
    +import org.apache.logging.log4j.Logger;
    +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.logging.LogService;
    +import org.apache.geode.internal.net.SocketCreatorFactory;
    +import org.apache.geode.internal.process.PidUnavailableException;
    +import org.apache.geode.internal.process.ProcessStreamReader.InputListener;
    +import org.apache.geode.internal.process.ProcessType;
    +import org.apache.geode.internal.process.ProcessUtils;
    +import org.apache.geode.internal.process.lang.AvailablePid;
    +import org.apache.geode.internal.util.StopWatch;
    +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 {
    +  protected static final Logger logger = LogService.getLogger();
    +
    +  protected static final int WAIT_FOR_PROCESS_TO_DIE_TIMEOUT = 5 * 60 * 1000; // 5 minutes
    +  protected static final int TIMEOUT_MILLISECONDS = WAIT_FOR_PROCESS_TO_DIE_TIMEOUT;
    +  protected static final int WAIT_FOR_FILE_CREATION_TIMEOUT = 10 * 1000; // 10s
    +  protected static final int WAIT_FOR_FILE_DELETION_TIMEOUT = 10 * 1000; // 10s
    +  protected static final int WAIT_FOR_MBEAN_TIMEOUT = 10 * 1000; // 10s
    --- End diff --
    
    Unused field?


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] geode pull request #699: GEODE-3413: overhaul launcher and process classes a...

Posted by pdxrunner <gi...@git.apache.org>.
Github user pdxrunner commented on a diff in the pull request:

    https://github.com/apache/geode/pull/699#discussion_r132483129
  
    --- Diff: geode-core/src/test/java/org/apache/geode/distributed/LocatorLauncherLocalIntegrationTest.java ---
    @@ -14,745 +14,270 @@
      */
     package org.apache.geode.distributed;
     
    -import org.apache.geode.distributed.AbstractLauncher.Status;
    +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.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.distributed.LocatorLauncher.Builder;
     import org.apache.geode.distributed.LocatorLauncher.LocatorState;
     import org.apache.geode.distributed.internal.InternalLocator;
    -import org.apache.geode.internal.*;
    -import org.apache.geode.internal.net.SocketCreatorFactory;
    +import org.apache.geode.internal.GemFireVersion;
     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.apache.geode.test.junit.runners.CategoryWithParameterizedRunnerFactory;
    -import org.junit.After;
    -import org.junit.Before;
    -import org.junit.Ignore;
    -import org.junit.Test;
    -import org.junit.experimental.categories.Category;
    -import org.junit.runner.RunWith;
    -import org.junit.runners.Parameterized;
    -
    -import java.io.File;
    -import java.lang.management.ManagementFactory;
    -import java.net.BindException;
    -import java.net.InetAddress;
    -
    -import static org.apache.geode.distributed.ConfigurationProperties.*;
    -import static org.junit.Assert.*;
     
     /**
    - * Tests usage of LocatorLauncher as a local API in existing JVM.
    + * Integration tests for using {@link LocatorLauncher} as an in-process API within an existing JVM.
      *
      * @since GemFire 8.0
      */
     @Category(IntegrationTest.class)
    -@RunWith(Parameterized.class)
    -@Parameterized.UseParametersRunnerFactory(CategoryWithParameterizedRunnerFactory.class)
    -public class LocatorLauncherLocalIntegrationTest
    -    extends AbstractLocatorLauncherIntegrationTestCase {
    +public class LocatorLauncherLocalIntegrationTest extends LocatorLauncherIntegrationTestCase {
     
       @Before
    -  public final void setUpLocatorLauncherLocalIntegrationTest() throws Exception {
    +  public void setUpLocatorLauncherLocalIntegrationTest() 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 tearDownLocatorLauncherLocalIntegrationTest() throws Exception {
    +  public void tearDownLocatorLauncherLocalIntegrationTest() throws Exception {
         disconnectFromDS();
       }
     
       @Test
    -  public void testBuilderSetProperties() throws Throwable {
    -    this.launcher = new Builder().setForce(true).setMemberName(getUniqueName())
    -        .setPort(this.locatorPort).setWorkingDirectory(this.workingDirectory)
    -        .set(CLUSTER_CONFIGURATION_DIR, this.clusterConfigDirectory)
    -        .set(DISABLE_AUTO_RECONNECT, "true").set(LOG_LEVEL, "config").set(MCAST_PORT, "0").build();
    -
    -    try {
    -      assertEquals(Status.ONLINE, this.launcher.start().getStatus());
    -      waitForLocatorToStart(this.launcher, true);
    -
    -      final InternalLocator locator = this.launcher.getLocator();
    -      assertNotNull(locator);
    -
    -      final DistributedSystem distributedSystem = locator.getDistributedSystem();
    -
    -      assertNotNull(distributedSystem);
    -      assertEquals("true", distributedSystem.getProperties().getProperty(DISABLE_AUTO_RECONNECT));
    -      assertEquals("0", distributedSystem.getProperties().getProperty(MCAST_PORT));
    -      assertEquals("config", distributedSystem.getProperties().getProperty(LOG_LEVEL));
    -      assertEquals(getUniqueName(), distributedSystem.getProperties().getProperty(NAME));
    -    } catch (Throwable e) {
    -      this.errorCollector.addError(e);
    -    }
    -
    -    try {
    -      assertEquals(Status.STOPPED, this.launcher.stop().getStatus());
    -      assertNull(this.launcher.getLocator());
    -    } catch (Throwable e) {
    -      this.errorCollector.addError(e);
    -    }
    +  public void usesLocatorPortAsDefaultPort() throws Exception {
    +    launcher = givenLocatorLauncher();
    +
    +    assertThat(launcher.getPort()).isEqualTo(defaultLocatorPort);
       }
     
       @Test
    -  public void testIsAttachAPIFound() throws Exception {
    -    final ProcessControllerFactory factory = new ProcessControllerFactory();
    -    assertTrue(factory.isAttachAPIFound());
    +  public void startReturnsOnline() throws Exception {
    +    launcher = givenLocatorLauncher();
    +
    +    assertThat(launcher.start().getStatus()).isEqualTo(ONLINE);
       }
     
       @Test
    -  public void testStartCreatesPidFile() throws Throwable {
    -    this.launcher = new Builder().setMemberName(getUniqueName()).setPort(this.locatorPort)
    -        .setRedirectOutput(true).setWorkingDirectory(this.workingDirectory)
    -        .set(CLUSTER_CONFIGURATION_DIR, this.clusterConfigDirectory).set(LOG_LEVEL, "config")
    -        .build();
    -
    -    try {
    -      this.launcher.start();
    -      waitForLocatorToStart(this.launcher);
    -      assertEquals(Status.ONLINE, this.launcher.status().getStatus());
    -
    -      // validate the pid file and its contents
    -      this.pidFile = new File(this.temporaryFolder.getRoot(), ProcessType.LOCATOR.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 startWithPortUsesPort() throws Exception {
    +    LocatorLauncher launcher = startLocator(newBuilder().setPort(defaultLocatorPort));
    +
    +    assertThat(launcher.getLocator().getPort()).isEqualTo(defaultLocatorPort);
       }
     
       @Test
    -  public void testStartDeletesStaleControlFiles() throws Throwable {
    -    // create existing control files
    -    this.stopRequestFile =
    -        new File(this.temporaryFolder.getRoot(), ProcessType.LOCATOR.getStopRequestFileName());
    -    this.stopRequestFile.createNewFile();
    -    assertTrue(this.stopRequestFile.exists());
    -
    -    this.statusRequestFile =
    -        new File(this.temporaryFolder.getRoot(), ProcessType.LOCATOR.getStatusRequestFileName());
    -    this.statusRequestFile.createNewFile();
    -    assertTrue(this.statusRequestFile.exists());
    -
    -    this.statusFile =
    -        new File(this.temporaryFolder.getRoot(), ProcessType.LOCATOR.getStatusFileName());
    -    this.statusFile.createNewFile();
    -    assertTrue(this.statusFile.exists());
    -
    -    // build and start the locator
    -    final Builder builder = new Builder().setMemberName(getUniqueName()).setPort(this.locatorPort)
    -        .setRedirectOutput(true).setWorkingDirectory(this.workingDirectory)
    -        .set(CLUSTER_CONFIGURATION_DIR, this.clusterConfigDirectory).set(LOG_LEVEL, "config");
    -
    -    assertFalse(builder.getForce());
    -    this.launcher = builder.build();
    -    assertFalse(this.launcher.isForcing());
    -    this.launcher.start();
    -
    -    try {
    -      waitForLocatorToStart(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.LOCATOR.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(stopRequestFile.exists());
    -      assertFalse(statusRequestFile.exists());
    -      assertFalse(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 startWithPortZeroUsesAnEphemeralPort() throws Exception {
    +    LocatorLauncher launcher = startLocator(newBuilder().setPort(0));
    +
    +    assertThat(launcher.getLocator().getPort()).isGreaterThan(0);
    +    assertThat(launcher.getLocator().isPeerLocator()).isTrue();
       }
     
       @Test
    -  public void testStartOverwritesStalePidFile() throws Throwable {
    -    // create existing pid file
    -    this.pidFile = new File(this.temporaryFolder.getRoot(), ProcessType.LOCATOR.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 locator
    -    final Builder builder = new Builder().setMemberName(getUniqueName()).setPort(this.locatorPort)
    -        .setRedirectOutput(true).setWorkingDirectory(this.workingDirectory)
    -        .set(CLUSTER_CONFIGURATION_DIR, this.clusterConfigDirectory).set(LOG_LEVEL, "config");
    -
    -    assertFalse(builder.getForce());
    -    this.launcher = builder.build();
    -    assertFalse(this.launcher.isForcing());
    -    this.launcher.start();
    -
    -    try {
    -      waitForLocatorToStart(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 startUsesBuilderValues() throws Exception {
    +    LocatorLauncher launcher = startLocator(newBuilder().setPort(nonDefaultLocatorPort));
    +
    +    InternalLocator locator = launcher.getLocator();
    +    assertThat(locator.getPort()).isEqualTo(nonDefaultLocatorPort);
    +
    +    DistributedSystem system = locator.getDistributedSystem();
    +    assertThat(system.getProperties().getProperty(DISABLE_AUTO_RECONNECT)).isEqualTo("true");
    +    assertThat(system.getProperties().getProperty(LOG_LEVEL)).isEqualTo("config");
    +    assertThat(system.getProperties().getProperty(MCAST_PORT)).isEqualTo("0");
    +    assertThat(system.getProperties().getProperty(NAME)).isEqualTo(getUniqueName());
       }
     
       @Test
    -  @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.LOCATOR.getPidFileName());
    -   * final int realPid = Host.getHost(0).getVM(3).invoke(() -> ProcessUtils.identifyPid());
    -   * assertFalse(realPid == ProcessUtils.identifyPid()); writePid(this.pidFile, realPid);
    -   * 
    -   * // build and start the locator final Builder builder = new Builder() .setForce(true)
    -   * .setMemberName(getUniqueName()) .setPort(this.locatorPort) .setRedirectOutput(true)
    -   * 
    -   * assertTrue(builder.getForce()); this.launcher = builder.build();
    -   * assertTrue(this.launcher.isForcing()); this.launcher.start();
    -   * 
    -   * // collect and throw the FIRST failure Throwable failure = null;
    -   * 
    -   * try { waitForLocatorToStart(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 startCreatesPidFile() throws Exception {
    +    startLocator();
    +
    +    assertThat(getPidFile()).exists();
    +  }
    +
    +  @Test
    +  public void pidFileContainsServerPid() throws Exception {
    +    startLocator();
    +
    +    assertThat(getLocatorPid()).isEqualTo(localPid);
    +  }
    +
    +  @Test
    +  public void startDeletesStaleControlFiles() throws Exception {
    +    File stopRequestFile = givenControlFile(getProcessType().getStopRequestFileName());
    +    File statusRequestFile = givenControlFile(getProcessType().getStatusRequestFileName());
    +    File statusFile = givenControlFile(getProcessType().getStatusFileName());
    +
    +    startLocator();
    +
    +    assertDeletionOf(stopRequestFile);
    +    assertDeletionOf(statusRequestFile);
    +    assertDeletionOf(statusFile);
    +  }
     
       @Test
    -  public void testStartWithDefaultPortInUseFails() throws Throwable {
    -    // Test makes no sense in this case
    -    if (this.locatorPort == 0) {
    -      return;
    -    }
    -
    -    this.socket =
    -        SocketCreatorFactory.getSocketCreatorForComponent(SecurableCommunicationChannel.CLUSTER)
    -            .createServerSocket(this.locatorPort, 50, null, -1);
    -    assertTrue(this.socket.isBound());
    -    assertFalse(this.socket.isClosed());
    -    assertFalse(AvailablePort.isPortAvailable(this.locatorPort, AvailablePort.SOCKET));
    -
    -    assertNotNull(System.getProperty(DistributionLocator.TEST_OVERRIDE_DEFAULT_PORT_PROPERTY));
    -    assertEquals(this.locatorPort,
    -        Integer.valueOf(System.getProperty(DistributionLocator.TEST_OVERRIDE_DEFAULT_PORT_PROPERTY))
    -            .intValue());
    -    assertFalse(AvailablePort.isPortAvailable(this.locatorPort, AvailablePort.SOCKET));
    -
    -    this.launcher = new Builder().setMemberName(getUniqueName()).setRedirectOutput(true)
    -        .setWorkingDirectory(this.workingDirectory)
    -        .set(CLUSTER_CONFIGURATION_DIR, this.clusterConfigDirectory).set(LOG_LEVEL, "config")
    -        .build();
    -
    -    assertEquals(this.locatorPort, this.launcher.getPort().intValue());
    -
    -    RuntimeException expected = null;
    -    try {
    -      this.launcher.start();
    -
    -      // why did it not fail like it's supposed to?
    -      final String property =
    -          System.getProperty(DistributionLocator.TEST_OVERRIDE_DEFAULT_PORT_PROPERTY);
    -      assertNotNull(property);
    -      assertEquals(this.locatorPort, Integer.valueOf(property).intValue());
    -      assertFalse(AvailablePort.isPortAvailable(this.locatorPort, AvailablePort.SOCKET));
    -      assertEquals(this.locatorPort, this.launcher.getPort().intValue());
    -      assertEquals(this.locatorPort, this.socket.getLocalPort());
    -      assertTrue(this.socket.isBound());
    -      assertFalse(this.socket.isClosed());
    -
    -      fail("LocatorLauncher 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.LOCATOR.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...
    -    LocatorState 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 startOverwritesStalePidFile() throws Exception {
    +    givenPidFile(fakePid);
    +
    +    startLocator();
    +
    +    assertThat(getLocatorPid()).isNotEqualTo(fakePid);
       }
     
       @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.LOCATOR.getPidFileName());
    -                          * writePid(this.pidFile, realPid);
    -                          * 
    -                          * // build and start the locator final Builder builder = new Builder()
    -                          * .setMemberName(getUniqueName()) .setPort(this.locatorPort)
    -                          * .setRedirectOutput(true) .set(logLevel, "config");
    -                          * 
    -                          * 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("LocatorLauncher start should have thrown RuntimeException caused by FileAlreadyExistsException"
    -                          * ); } catch (RuntimeException e) { expected = e;
    -                          * assertNotNull(expected.getMessage()); assertTrue(expected.getMessage(),
    -                          * expected.getMessage().
    -                          * contains("A PID file already exists and a Locator may be running in"));
    -                          * assertIndexDetailsEquals(RuntimeException.class, expected.getClass()); }
    -                          * catch (Throwable e) { logger.error(e); if (failure == null) { failure =
    -                          * e; } }
    -                          * 
    -                          * // just in case the launcher started... LocatorState 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.locator.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 startWithDefaultPortInUseFailsWithBindException() throws Exception {
    +    givenLocatorPortInUse(defaultLocatorPort);
    +
    +    launcher = new Builder().build();
    +
    +    assertThatThrownBy(() -> launcher.start()).isInstanceOf(RuntimeException.class)
    +        .hasCauseInstanceOf(BindException.class);
    +  }
     
       @Test
    -  public void testStartUsingPort() throws Throwable {
    -    // generate one free port and then use it instead of default
    -    final int freeTCPPort = AvailablePortHelper.getRandomAvailableTCPPort();
    -    assertTrue(AvailablePort.isPortAvailable(freeTCPPort, AvailablePort.SOCKET));
    -
    -    this.launcher = new Builder().setMemberName(getUniqueName()).setPort(freeTCPPort)
    -        .setRedirectOutput(true).setWorkingDirectory(this.workingDirectory)
    -        .set(CLUSTER_CONFIGURATION_DIR, this.clusterConfigDirectory).set(LOG_LEVEL, "config")
    -        .build();
    -
    -    int pid = 0;
    -    try {
    -      // if start succeeds without throwing exception then #47778 is fixed
    -      this.launcher.start();
    -      waitForLocatorToStart(this.launcher);
    -
    -      // validate the pid file and its contents
    -      this.pidFile = new File(this.temporaryFolder.getRoot(), ProcessType.LOCATOR.getPidFileName());
    -      assertTrue(pidFile.exists());
    -      pid = readPid(pidFile);
    -      assertTrue(pid > 0);
    -      assertTrue(ProcessUtils.isProcessAlive(pid));
    -      assertEquals(getPid(), pid);
    -
    -      // verify locator did not use default port
    -      assertTrue(AvailablePort.isPortAvailable(this.locatorPort, AvailablePort.SOCKET));
    -
    -      final LocatorState status = this.launcher.status();
    -      final String portString = status.getPort();
    -      assertEquals("Port should be \"" + freeTCPPort + "\" instead of " + portString,
    -          String.valueOf(freeTCPPort), portString);
    -    } catch (Throwable e) {
    -      this.errorCollector.addError(e);
    -    }
    -
    -    // stop the locator
    -    try {
    -      assertEquals(Status.STOPPED, this.launcher.stop().getStatus());
    -      waitForFileToDelete(this.pidFile);
    -    } catch (Throwable e) {
    -      this.errorCollector.addError(e);
    -    }
    +  public void startWithLocatorPortInUseFailsWithBindException() throws Exception {
    +    givenServerPortInUse(nonDefaultLocatorPort);
    +
    +    launcher = new Builder().setPort(nonDefaultLocatorPort).build();
    +
    +    assertThatThrownBy(() -> this.launcher.start()).isInstanceOf(RuntimeException.class)
    +        .hasCauseInstanceOf(BindException.class);
       }
     
       @Test
    -  public void testStartUsingPortInUseFails() throws Throwable {
    -    // Test makes no sense in this case
    -    if (this.locatorPort == 0) {
    -      return;
    -    }
    -
    -    // generate one free port and then use it instead of default
    -    this.socket =
    -        SocketCreatorFactory.getSocketCreatorForComponent(SecurableCommunicationChannel.CLUSTER)
    -            .createServerSocket(this.locatorPort, 50, null, -1);
    -
    -    this.launcher = new Builder().setMemberName(getUniqueName()).setPort(this.locatorPort)
    -        .setRedirectOutput(true).setWorkingDirectory(this.workingDirectory)
    -        .set(CLUSTER_CONFIGURATION_DIR, this.clusterConfigDirectory).set(LOG_LEVEL, "config")
    -        .build();
    -
    -    RuntimeException expected = null;
    -    try {
    -      this.launcher.start();
    -      fail("LocatorLauncher 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.LOCATOR.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...
    -    LocatorState 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 statusWithPidReturnsOnlineWithDetails() throws Exception {
    +    givenRunningLocator();
    +
    +    LocatorState locatorState = new Builder().setPid(localPid).build().status();
    +
    +    assertThat(locatorState.getStatus()).isEqualTo(ONLINE);
    +    assertThat(locatorState.getClasspath()).isEqualTo(getClassPath());
    +    assertThat(locatorState.getGemFireVersion()).isEqualTo(GemFireVersion.getGemFireVersion());
    +    assertThat(locatorState.getHost()).isEqualTo(InetAddress.getLocalHost().getCanonicalHostName());
    --- End diff --
    
    This assertion may fail in IDE's test environment. It would be great to have something that works reliably for host name/IP in all build & test environments: IDEs, Concourse,  & Jenkins.
    
    OK, maybe it's just my local machine configuration. If I have an alias for `localhost` in my `/etc/hosts` file, then this comparison fails. With no alias, then it works as expected. (MacOS)


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] geode pull request #699: GEODE-3413: overhaul launcher and process classes a...

Posted by pdxrunner <gi...@git.apache.org>.
Github user pdxrunner commented on a diff in the pull request:

    https://github.com/apache/geode/pull/699#discussion_r132325049
  
    --- Diff: geode-core/src/main/java/org/apache/geode/distributed/LocatorLauncher.java ---
    @@ -1075,8 +1082,7 @@ private LocatorState stopWithWorkingDirectory() {
         try {
           final ProcessController controller =
               new ProcessControllerFactory().createProcessController(this.controllerParameters,
    -              new File(getWorkingDirectory()), ProcessType.LOCATOR.getPidFileName(),
    -              READ_PID_FILE_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS);
    +              new File(getWorkingDirectory()), ProcessType.LOCATOR.getPidFileName());
           parsedPid = controller.getProcessId();
     
           // NOTE in-process request will go infinite loop unless we do the following
    --- End diff --
    
    There are several opportunities for collapsing multiple catch blocks in this class, such as the try/catch that starts at line 1082


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---