You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@geode.apache.org by kl...@apache.org on 2017/08/11 17:12:00 UTC
[02/14] geode git commit: GEODE-3413: overhaul launcher and process
classes and tests
http://git-wip-us.apache.org/repos/asf/geode/blob/894f3ee7/geode-core/src/test/java/org/apache/geode/internal/process/NativeProcessUtilsIntegrationTest.java
----------------------------------------------------------------------
diff --git a/geode-core/src/test/java/org/apache/geode/internal/process/NativeProcessUtilsIntegrationTest.java b/geode-core/src/test/java/org/apache/geode/internal/process/NativeProcessUtilsIntegrationTest.java
new file mode 100644
index 0000000..000318c
--- /dev/null
+++ b/geode-core/src/test/java/org/apache/geode/internal/process/NativeProcessUtilsIntegrationTest.java
@@ -0,0 +1,119 @@
+/*
+ * 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.MINUTES;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.awaitility.Awaitility.await;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+import org.junit.rules.TemporaryFolder;
+
+import org.apache.geode.internal.util.StopWatch;
+import org.apache.geode.test.junit.categories.IntegrationTest;
+
+/**
+ * Functional integration tests for {@link NativeProcessUtils}.
+ */
+@Category(IntegrationTest.class)
+public class NativeProcessUtilsIntegrationTest {
+
+ /** Max sleep timeout for {@link ProcessSleeps} */
+ private static final int PROCESS_TIMEOUT_MILLIS = 10 * 60 * 1000;
+
+ private static final String FILE_NAME = "pid.txt";
+
+ private NativeProcessUtils nativeProcessUtils;
+ private Process process;
+ private File pidFile;
+ private int pid;
+
+ @Rule
+ public TemporaryFolder temporaryFolder = new TemporaryFolder();
+
+ @Before
+ public void before() throws Exception {
+ File directory = temporaryFolder.getRoot();
+
+ List<String> command = new ArrayList<>();
+ command
+ .add(new File(new File(System.getProperty("java.home"), "bin"), "java").getCanonicalPath());
+ command.add("-cp");
+ command.add(System.getProperty("java.class.path"));
+ command.add(ProcessSleeps.class.getName());
+
+ process = new ProcessBuilder(command).directory(directory).start();
+ assertThat(process.isAlive()).isTrue();
+
+ pidFile = new File(directory, FILE_NAME);
+ await().atMost(2, MINUTES).until(() -> assertThat(pidFile).exists());
+
+ pid = new PidFile(pidFile).readPid();
+ assertThat(pid).isGreaterThan(0);
+
+ nativeProcessUtils = new NativeProcessUtils();
+ }
+
+ @After
+ public void after() throws Exception {
+ process.destroyForcibly();
+ }
+
+ @Test
+ public void killProcessKillsOtherProcess() throws Exception {
+ // act
+ nativeProcessUtils.killProcess(pid);
+
+ // assert
+ await().atMost(2, MINUTES).until(() -> assertThat(process.isAlive()).isFalse());
+ }
+
+ @Test
+ public void isProcessAliveReturnsTrueForLiveProcess() throws Exception {
+ // act/assert
+ assertThat(nativeProcessUtils.isProcessAlive(pid)).isTrue();
+ }
+
+ @Test
+ public void isProcessAliveReturnsFalseForDeadProcess() throws Exception {
+ // arrange
+ process.destroyForcibly();
+
+ // act/assert
+ await().atMost(2, MINUTES).until(() -> assertThat(process.isAlive()).isFalse());
+ assertThat(nativeProcessUtils.isProcessAlive(pid)).isFalse();
+ }
+
+ /**
+ * Class with main that uses LocalProcessLauncher to create a PidFile and then sleeps.
+ */
+ protected static class ProcessSleeps {
+ public static void main(final String... args) throws Exception {
+ new LocalProcessLauncher(new File(FILE_NAME), false);
+ StopWatch stopWatch = new StopWatch(true);
+ while (stopWatch.elapsedTimeMillis() < PROCESS_TIMEOUT_MILLIS) {
+ Thread.sleep(1000);
+ }
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/geode/blob/894f3ee7/geode-core/src/test/java/org/apache/geode/internal/process/NativeProcessUtilsTest.java
----------------------------------------------------------------------
diff --git a/geode-core/src/test/java/org/apache/geode/internal/process/NativeProcessUtilsTest.java b/geode-core/src/test/java/org/apache/geode/internal/process/NativeProcessUtilsTest.java
new file mode 100644
index 0000000..9c845b8
--- /dev/null
+++ b/geode-core/src/test/java/org/apache/geode/internal/process/NativeProcessUtilsTest.java
@@ -0,0 +1,76 @@
+/*
+ * 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.ProcessUtils.identifyPid;
+import static org.assertj.core.api.Assertions.assertThat;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+
+import org.apache.geode.internal.process.lang.AvailablePid;
+import org.apache.geode.test.junit.Retry;
+import org.apache.geode.test.junit.categories.UnitTest;
+import org.apache.geode.test.junit.rules.RetryRule;
+
+/**
+ * Unit tests for {@link NativeProcessUtils}.
+ *
+ * <p>
+ * Tests involving fakePid use {@link RetryRule} because the fakePid may become used by a real
+ * process before the test executes.
+ */
+@Category(UnitTest.class)
+public class NativeProcessUtilsTest {
+
+ private static final int PREFERRED_FAKE_PID = 42;
+
+ private int actualPid;
+ private int fakePid;
+ private NativeProcessUtils nativeProcessUtils;
+
+ @Rule
+ public RetryRule retryRule = new RetryRule();
+
+ @Before
+ public void before() throws Exception {
+ actualPid = identifyPid();
+ fakePid = new AvailablePid().findAvailablePid(PREFERRED_FAKE_PID);
+ nativeProcessUtils = new NativeProcessUtils();
+ }
+
+ @Test
+ public void isAttachApiAvailable_returnsFalse() throws Exception {
+ assertThat(nativeProcessUtils.isAttachApiAvailable()).isFalse();
+ }
+
+ @Test
+ public void isAvailable_returnsTrue() throws Exception {
+ assertThat(nativeProcessUtils.isAvailable()).isTrue();
+ }
+
+ @Test
+ public void isProcessAlive_livePid_returnsTrue() throws Exception {
+ assertThat(nativeProcessUtils.isProcessAlive(actualPid)).isTrue();
+ }
+
+ @Test
+ @Retry(3)
+ public void isProcessAlive_deadPid_returnsFalse() throws Exception {
+ assertThat(nativeProcessUtils.isProcessAlive(fakePid)).isFalse();
+ }
+}
http://git-wip-us.apache.org/repos/asf/geode/blob/894f3ee7/geode-core/src/test/java/org/apache/geode/internal/process/NonBlockingProcessStreamReaderIntegrationTest.java
----------------------------------------------------------------------
diff --git a/geode-core/src/test/java/org/apache/geode/internal/process/NonBlockingProcessStreamReaderIntegrationTest.java b/geode-core/src/test/java/org/apache/geode/internal/process/NonBlockingProcessStreamReaderIntegrationTest.java
new file mode 100755
index 0000000..05b7cbc
--- /dev/null
+++ b/geode-core/src/test/java/org/apache/geode/internal/process/NonBlockingProcessStreamReaderIntegrationTest.java
@@ -0,0 +1,130 @@
+/*
+ * 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 org.junit.Test;
+import org.junit.experimental.categories.Category;
+
+import org.apache.geode.internal.process.ProcessStreamReader.ReadingMode;
+import org.apache.geode.test.junit.categories.IntegrationTest;
+
+/**
+ * Functional integration tests for NonBlockingProcessStreamReader which was introduced to fix TRAC
+ * #51967: "GFSH start hangs on Windows"
+ *
+ * @see BlockingProcessStreamReaderIntegrationTest
+ * @see BlockingProcessStreamReaderWindowsTest
+ *
+ * @since GemFire 8.2
+ */
+@Category(IntegrationTest.class)
+public class NonBlockingProcessStreamReaderIntegrationTest
+ extends BaseProcessStreamReaderIntegrationTest {
+
+ /**
+ * This test hangs on Windows if the implementation is blocking instead of non-blocking. Geode
+ * will always use the non-blocking implementation on Windows. If someone accidentally changes
+ * this, then the probably the first thing you'll notice is this test hanging.
+ */
+ @Test
+ public void canCloseStreamsWhileProcessIsAlive() throws Exception {
+ // arrange
+ givenRunningProcessWithStreamReaders(ProcessSleeps.class);
+
+ // act
+ process.getOutputStream().close();
+ process.getErrorStream().close();
+ process.getInputStream().close();
+
+ // assert
+ assertThatProcessIsAlive(process);
+ }
+
+ @Test
+ public void canStopReadersWhileProcessIsAlive() throws Exception {
+ // arrange
+ givenRunningProcessWithStreamReaders(ProcessSleeps.class);
+
+ // act
+ stdout.stop();
+ stderr.stop();
+
+ // assert
+ assertThatProcessIsAlive(process);
+ }
+
+ @Test
+ public void capturesStdoutWhileProcessIsAlive() throws Exception {
+ // arrange
+ givenStartedProcessWithStreamListeners(ProcessPrintsToStdout.class);
+
+ // act
+ waitUntilProcessStops();
+
+ // assert
+ assertThatProcessAndReadersStopped();
+ assertThatStdOutContainsExactly(ProcessPrintsToStdout.STDOUT);
+ assertThatStdErrContainsExactly(ProcessPrintsToStdout.STDERR);
+ }
+
+ @Test
+ public void capturesStderrWhileProcessIsAlive() throws Exception {
+ // arrange
+ givenStartedProcessWithStreamListeners(ProcessPrintsToStderr.class);
+
+ // act
+ waitUntilProcessStops();
+
+ // assert
+ assertThatProcessAndReadersStopped();
+ assertThatStdOutContainsExactly(ProcessPrintsToStderr.STDOUT);
+ assertThatStdErrContainsExactly(ProcessPrintsToStderr.STDERR);
+ }
+
+ @Test
+ public void capturesBothWhileProcessIsAlive() throws Exception {
+ // arrange
+ givenStartedProcessWithStreamListeners(ProcessPrintsToBoth.class);
+
+ // act
+ waitUntilProcessStops();
+
+ // assert
+ assertThatProcessAndReadersStopped();
+ assertThatStdOutContainsExactly(ProcessPrintsToBoth.STDOUT);
+ assertThatStdErrContainsExactly(ProcessPrintsToBoth.STDERR);
+ }
+
+ @Test
+ public void capturesStderrWhenProcessFailsDuringStart() throws Exception {
+ // arrange
+ givenStartedProcessWithStreamListeners(ProcessThrowsError.class);
+
+ // act
+ waitUntilProcessStops();
+
+ // assert
+ assertThatProcessAndReadersStoppedWithExitValue(1);
+ assertThatStdOutContainsExactly(ProcessThrowsError.STDOUT);
+ assertThatStdErrContains(ProcessThrowsError.ERROR_MSG);
+ }
+
+ @Override
+ protected ReadingMode getReadingMode() {
+ return NON_BLOCKING;
+ }
+}
http://git-wip-us.apache.org/repos/asf/geode/blob/894f3ee7/geode-core/src/test/java/org/apache/geode/internal/process/NonBlockingProcessStreamReaderJUnitTest.java
----------------------------------------------------------------------
diff --git a/geode-core/src/test/java/org/apache/geode/internal/process/NonBlockingProcessStreamReaderJUnitTest.java b/geode-core/src/test/java/org/apache/geode/internal/process/NonBlockingProcessStreamReaderJUnitTest.java
deleted file mode 100755
index 105e7f0..0000000
--- a/geode-core/src/test/java/org/apache/geode/internal/process/NonBlockingProcessStreamReaderJUnitTest.java
+++ /dev/null
@@ -1,365 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more contributor license
- * agreements. See the NOTICE file distributed with this work for additional information regarding
- * copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance with the License. You may obtain a
- * copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software distributed under the License
- * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
- * or implied. See the License for the specific language governing permissions and limitations under
- * the License.
- */
-package org.apache.geode.internal.process;
-
-import static org.junit.Assert.*;
-
-import java.util.concurrent.Callable;
-
-import org.junit.Test;
-import org.junit.experimental.categories.Category;
-
-import org.apache.geode.internal.process.ProcessStreamReader.InputListener;
-import org.apache.geode.internal.process.ProcessStreamReader.ReadingMode;
-import org.apache.geode.test.junit.categories.IntegrationTest;
-
-/**
- * Tests NonBlockingProcessStreamReader which was introduced to fix TRAC bug #51967.
- *
- * None of the tests should be skipped or hang on Windows.
- *
- * @since GemFire 8.2
- */
-@Category(IntegrationTest.class)
-public class NonBlockingProcessStreamReaderJUnitTest extends ProcessStreamReaderTestCase {
-
- @Test
- public void canCloseStreamsWhileProcessIsAlive() throws Exception {
- this.process = new ProcessBuilder(createCommandLine(ProcessSleeps.class)).start();
-
- this.stderr = new ProcessStreamReader.Builder(this.process)
- .inputStream(this.process.getErrorStream()).readingMode(ReadingMode.NON_BLOCKING).build();
-
- this.stdout = new ProcessStreamReader.Builder(this.process)
- .inputStream(this.process.getInputStream()).readingMode(ReadingMode.NON_BLOCKING).build();
-
- this.stderr.start();
- this.stdout.start();
-
- assertIsAlive(this.process);
-
- assertEventuallyIsRunning(this.stderr);
- assertEventuallyIsRunning(this.stdout);
-
- this.process.getErrorStream().close();
- this.process.getOutputStream().close();
- this.process.getInputStream().close();
-
- this.stderr.stop();
- this.stdout.stop();
-
- assertIsAlive(this.process);
-
- this.process.destroy();
- }
-
- @Test
- public void canStopReadersWhileProcessIsAlive() throws Exception {
- this.process = new ProcessBuilder(createCommandLine(ProcessSleeps.class)).start();
-
- this.stderr = new ProcessStreamReader.Builder(this.process)
- .inputStream(this.process.getErrorStream()).readingMode(ReadingMode.NON_BLOCKING).build();
-
- this.stdout = new ProcessStreamReader.Builder(this.process)
- .inputStream(this.process.getInputStream()).readingMode(ReadingMode.NON_BLOCKING).build();
-
- this.stderr.start();
- this.stdout.start();
-
- assertIsAlive(this.process);
-
- assertEventuallyIsRunning(this.stderr);
- assertEventuallyIsRunning(this.stdout);
-
- this.stderr.stop();
- this.stdout.stop();
-
- this.process.getErrorStream().close();
- this.process.getOutputStream().close();
- this.process.getInputStream().close();
-
- assertIsAlive(this.process);
-
- this.process.destroy();
- }
-
- @Test
- public void capturesStdoutWhileProcessIsAlive() throws Exception {
- this.process = new ProcessBuilder(createCommandLine(ProcessPrintsToStdout.class)).start();
-
- final StringBuffer stderrBuffer = new StringBuffer();
- InputListener stderrListener = new InputListener() {
- @Override
- public void notifyInputLine(String line) {
- stderrBuffer.append(line);
- }
- };
-
- final StringBuffer stdoutBuffer = new StringBuffer();
- InputListener stdoutListener = new InputListener() {
- @Override
- public void notifyInputLine(String line) {
- stdoutBuffer.append(line);
- }
- };
-
- this.stderr =
- new ProcessStreamReader.Builder(this.process).inputStream(this.process.getErrorStream())
- .inputListener(stderrListener).readingMode(ReadingMode.NON_BLOCKING).build();
-
- this.stdout =
- new ProcessStreamReader.Builder(this.process).inputStream(this.process.getInputStream())
- .inputListener(stdoutListener).readingMode(ReadingMode.NON_BLOCKING).build();
-
- this.stderr.start();
- this.stdout.start();
-
- // wait for process to die
- assertEventuallyFalse("Process never died", new Callable<Boolean>() {
- @Override
- public Boolean call() throws Exception {
- return ProcessUtils.isProcessAlive(process);
- }
- }, WAIT_FOR_PROCESS_TO_DIE_TIMEOUT, INTERVAL);
-
- final int exitValue = this.process.exitValue();
- assertEquals(0, exitValue);
-
- this.stderr.join(READER_JOIN_TIMEOUT);
- assertFalse(this.stderr.isRunning());
-
- this.stdout.join(READER_JOIN_TIMEOUT);
- assertFalse(this.stdout.isRunning());
-
- // System.out.println("Stopping ProcessStreamReader");
- this.stderr.stop();
- this.stdout.stop();
-
- // System.out.println("stderr=\n" + stderrBuffer.toString());
- assertEquals("", stderrBuffer.toString());
-
- // System.out.println("stdout=\n" + stdoutBuffer.toString());
- StringBuilder sb = new StringBuilder().append(ProcessPrintsToStdout.LINES[0])
- .append(ProcessPrintsToStdout.LINES[1]).append(ProcessPrintsToStdout.LINES[2]);
- assertEquals(sb.toString(), stdoutBuffer.toString());
-
- // System.out.println("Closing streams");
- this.process.getErrorStream().close();
- this.process.getInputStream().close();
-
- this.process.destroy();
- }
-
- @Test
- public void capturesStderrWhileProcessIsAlive() throws Exception {
- this.process = new ProcessBuilder(createCommandLine(ProcessPrintsToStderr.class)).start();
-
- final StringBuffer stderrBuffer = new StringBuffer();
- InputListener stderrListener = new InputListener() {
- @Override
- public void notifyInputLine(String line) {
- stderrBuffer.append(line);
- }
- };
-
- final StringBuffer stdoutBuffer = new StringBuffer();
- InputListener stdoutListener = new InputListener() {
- @Override
- public void notifyInputLine(String line) {
- stdoutBuffer.append(line);
- }
- };
-
- this.stderr =
- new ProcessStreamReader.Builder(this.process).inputStream(this.process.getErrorStream())
- .inputListener(stderrListener).readingMode(ReadingMode.NON_BLOCKING).build();
-
- this.stdout =
- new ProcessStreamReader.Builder(this.process).inputStream(this.process.getInputStream())
- .inputListener(stdoutListener).readingMode(ReadingMode.NON_BLOCKING).build();
-
- this.stderr.start();
- this.stdout.start();
-
- // wait for process to die
- assertEventuallyFalse("Process never died", new Callable<Boolean>() {
- @Override
- public Boolean call() throws Exception {
- return ProcessUtils.isProcessAlive(process);
- }
- }, WAIT_FOR_PROCESS_TO_DIE_TIMEOUT, INTERVAL);
-
- final int exitValue = this.process.exitValue();
- assertEquals(0, exitValue);
-
- this.stderr.join(READER_JOIN_TIMEOUT);
- assertFalse(this.stderr.isRunning());
-
- this.stdout.join(READER_JOIN_TIMEOUT);
- assertFalse(this.stdout.isRunning());
-
- // System.out.println("Stopping ProcessStreamReader");
- this.stderr.stop();
- this.stdout.stop();
-
- // System.out.println("stderr=\n" + stderrBuffer.toString());
- StringBuilder sb = new StringBuilder().append(ProcessPrintsToStderr.LINES[0])
- .append(ProcessPrintsToStderr.LINES[1]).append(ProcessPrintsToStderr.LINES[2]);
- assertEquals(sb.toString(), stderrBuffer.toString());
-
- // System.out.println("stdout=\n" + stdoutBuffer.toString());
- assertEquals("", stdoutBuffer.toString());
-
- // System.out.println("Closing streams");
- this.process.getErrorStream().close();
- this.process.getInputStream().close();
-
- this.process.destroy();
- }
-
- @Test
- public void capturesBothWhileProcessIsAlive() throws Exception {
- this.process = new ProcessBuilder(createCommandLine(ProcessPrintsToBoth.class)).start();
-
- final StringBuffer stderrBuffer = new StringBuffer();
- InputListener stderrListener = new InputListener() {
- @Override
- public void notifyInputLine(String line) {
- stderrBuffer.append(line);
- }
- };
-
- final StringBuffer stdoutBuffer = new StringBuffer();
- InputListener stdoutListener = new InputListener() {
- @Override
- public void notifyInputLine(String line) {
- stdoutBuffer.append(line);
- }
- };
-
- this.stderr =
- new ProcessStreamReader.Builder(this.process).inputStream(this.process.getErrorStream())
- .inputListener(stderrListener).readingMode(ReadingMode.NON_BLOCKING).build();
-
- this.stdout =
- new ProcessStreamReader.Builder(this.process).inputStream(this.process.getInputStream())
- .inputListener(stdoutListener).readingMode(ReadingMode.NON_BLOCKING).build();
-
- this.stderr.start();
- this.stdout.start();
-
- // wait for process to die
- assertEventuallyFalse("Process never died", new Callable<Boolean>() {
- @Override
- public Boolean call() throws Exception {
- return ProcessUtils.isProcessAlive(process);
- }
- }, WAIT_FOR_PROCESS_TO_DIE_TIMEOUT, INTERVAL);
-
- final int exitValue = this.process.exitValue();
- assertEquals(0, exitValue);
-
- this.stderr.join(READER_JOIN_TIMEOUT);
- assertFalse(this.stderr.isRunning());
-
- this.stdout.join(READER_JOIN_TIMEOUT);
- assertFalse(this.stdout.isRunning());
-
- // System.out.println("Stopping ProcessStreamReader");
- this.stderr.stop();
- this.stdout.stop();
-
- // System.out.println("stderr=\n" + stderrBuffer.toString());
- StringBuilder sb = new StringBuilder().append(ProcessPrintsToBoth.ERR_LINES[0])
- .append(ProcessPrintsToBoth.ERR_LINES[1]).append(ProcessPrintsToBoth.ERR_LINES[2]);
- assertEquals(sb.toString(), stderrBuffer.toString());
-
- // System.out.println("stdout=\n" + stdoutBuffer.toString());
- sb = new StringBuilder().append(ProcessPrintsToBoth.OUT_LINES[0])
- .append(ProcessPrintsToBoth.OUT_LINES[1]).append(ProcessPrintsToBoth.OUT_LINES[2]);
- assertEquals(sb.toString(), stdoutBuffer.toString());
-
- // System.out.println("Closing streams");
- this.process.getErrorStream().close();
- this.process.getInputStream().close();
-
- this.process.destroy();
- }
-
- @Test
- public void capturesStderrWhenProcessFailsDuringStart() throws Exception {
- this.process = new ProcessBuilder(createCommandLine(ProcessThrowsError.class)).start();
-
- final StringBuffer stderrBuffer = new StringBuffer();
- InputListener stderrListener = new InputListener() {
- @Override
- public void notifyInputLine(String line) {
- stderrBuffer.append(line);
- }
- };
-
- final StringBuffer stdoutBuffer = new StringBuffer();
- InputListener stdoutListener = new InputListener() {
- @Override
- public void notifyInputLine(String line) {
- stdoutBuffer.append(line);
- }
- };
-
- this.stderr =
- new ProcessStreamReader.Builder(this.process).inputStream(this.process.getErrorStream())
- .inputListener(stderrListener).readingMode(ReadingMode.NON_BLOCKING).build();
-
- this.stdout =
- new ProcessStreamReader.Builder(this.process).inputStream(this.process.getInputStream())
- .inputListener(stdoutListener).readingMode(ReadingMode.NON_BLOCKING).build();
-
- this.stderr.start();
- this.stdout.start();
-
- // wait for process to die
- assertEventuallyFalse("Process never died", new Callable<Boolean>() {
- @Override
- public Boolean call() throws Exception {
- return ProcessUtils.isProcessAlive(process);
- }
- }, WAIT_FOR_PROCESS_TO_DIE_TIMEOUT, INTERVAL);
-
- final int exitValue = this.process.exitValue();
- assertNotEquals(0, exitValue);
-
- this.stderr.join(READER_JOIN_TIMEOUT);
- assertFalse(this.stderr.isRunning());
-
- this.stdout.join(READER_JOIN_TIMEOUT);
- assertFalse(this.stdout.isRunning());
-
- // System.out.println("Stopping ProcessStreamReader");
- this.stderr.stop();
- this.stdout.stop();
-
- // System.out.println("stderr=\n" + stderrBuffer.toString());
- assertTrue(stderrBuffer.toString() + " does not contain " + ProcessThrowsError.ERROR_MSG,
- stderrBuffer.toString().contains(ProcessThrowsError.ERROR_MSG));
-
- // System.out.println("stdout=\n" + stdoutBuffer.toString());
-
- // System.out.println("Closing streams");
- this.process.getErrorStream().close();
- this.process.getInputStream().close();
-
- this.process.destroy();
- }
-}
http://git-wip-us.apache.org/repos/asf/geode/blob/894f3ee7/geode-core/src/test/java/org/apache/geode/internal/process/PidFileIntegrationTest.java
----------------------------------------------------------------------
diff --git a/geode-core/src/test/java/org/apache/geode/internal/process/PidFileIntegrationTest.java b/geode-core/src/test/java/org/apache/geode/internal/process/PidFileIntegrationTest.java
new file mode 100755
index 0000000..584f185
--- /dev/null
+++ b/geode-core/src/test/java/org/apache/geode/internal/process/PidFileIntegrationTest.java
@@ -0,0 +1,187 @@
+/*
+ * 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.ProcessUtils.identifyPid;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+import org.junit.rules.TemporaryFolder;
+
+import org.apache.geode.internal.process.io.IntegerFileWriter;
+import org.apache.geode.internal.process.lang.AvailablePid;
+import org.apache.geode.test.junit.categories.IntegrationTest;
+
+/**
+ * Functional integration tests for {@link PidFile}.
+ *
+ * @since GemFire 8.2
+ */
+@Category(IntegrationTest.class)
+public class PidFileIntegrationTest {
+
+ private File directory;
+ private File pidFile;
+ private String pidFileName;
+ private ExecutorService futures;
+ private int pid;
+
+ @Rule
+ public TemporaryFolder temporaryFolder = new TemporaryFolder();
+
+ @Before
+ public void before() throws Exception {
+ directory = temporaryFolder.getRoot();
+ pidFile = new File(directory, "pid.txt");
+ pidFileName = pidFile.getName();
+ futures = Executors.newFixedThreadPool(2);
+ pid = identifyPid();
+ }
+
+ @After
+ public void after() {
+ assertThat(this.futures.shutdownNow()).isEmpty();
+ }
+
+ @Test
+ public void readsIntFromFile() throws Exception {
+ // arrange
+ String value = "42";
+ new IntegerFileWriter(pidFile).writeToFile(value);
+
+ // act
+ int readValue = new PidFile(pidFile).readPid();
+
+ // assert
+ assertThat(readValue).isEqualTo(Integer.parseInt(value));
+ }
+
+ @Test
+ public void readingEmptyFileThrowsIllegalArgumentException() throws Exception {
+ // arrange
+ new IntegerFileWriter(pidFile).writeToFile("");
+
+ // act/assert
+ assertThatThrownBy(() -> new PidFile(pidFile).readPid())
+ .isInstanceOf(IllegalArgumentException.class);
+ }
+
+ @Test
+ public void readingFileWithNonIntegerThrowsIllegalArgumentException() throws Exception {
+ // arrange
+ String value = "forty two";
+ new IntegerFileWriter(pidFile).writeToFile(value);
+
+ // act/assert
+ assertThatThrownBy(() -> new PidFile(pidFile).readPid())
+ .isInstanceOf(IllegalArgumentException.class)
+ .hasMessageContaining("Invalid pid '" + value + "' found");
+ }
+
+ @Test
+ public void readingFileWithNegativeIntegerThrowsIllegalArgumentException() throws Exception {
+ // arrange
+ String value = "-42";
+ new IntegerFileWriter(pidFile).writeToFile(value);
+
+ // act/assert
+ assertThatThrownBy(() -> new PidFile(pidFile).readPid())
+ .isInstanceOf(IllegalArgumentException.class)
+ .hasMessageContaining("Invalid pid '" + value + "' found");
+ }
+
+ @Test
+ public void readingNullFileThrowsNullPointerException() throws Exception {
+ // arrange
+ pidFile = null;
+
+ // act/assert
+ assertThatThrownBy(() -> new PidFile(pidFile).readPid())
+ .isInstanceOf(IllegalArgumentException.class);
+ }
+
+ @Test
+ public void findsCorrectFileByName() throws Exception {
+ // arrange
+ new IntegerFileWriter(pidFile).writeToFile(pid);
+ int[] pids = new AvailablePid().findAvailablePids(4);
+ for (int i = 1; i <= pids.length; i++) {
+ new IntegerFileWriter(new File(directory, "pid" + i + ".txt")).writeToFile(pids[i - 1]);
+ }
+ assertThat(directory.listFiles()).hasSize(pids.length + 1);
+
+ // act
+ PidFile namedPidFile = new PidFile(directory, pidFile.getName());
+
+ // assert
+ assertThat(namedPidFile.getFile()).hasContent(String.valueOf(pid));
+ assertThat(namedPidFile.readPid()).isEqualTo(pid);
+ }
+
+ @Test
+ public void missingFileInEmptyDirectoryThrowsFileNotFoundException() throws Exception {
+ // arrange
+ assertThat(pidFile).doesNotExist();
+
+ // act/assert
+ assertThatThrownBy(() -> new PidFile(directory, pidFileName).readPid())
+ .isInstanceOf(FileNotFoundException.class).hasMessage(
+ "Unable to find PID file '" + pidFileName + "' in directory '" + directory + "'");
+ }
+
+ @Test
+ public void fileForDirectoryThrowsIllegalArgumentException() throws Exception {
+ // arrange
+ File directoryIsFile = temporaryFolder.newFile("my.file");
+
+ // act/assert
+ assertThatThrownBy(() -> new PidFile(directoryIsFile, pidFileName).readPid())
+ .isInstanceOf(IllegalArgumentException.class)
+ .hasMessage("Nonexistent directory '" + directoryIsFile + "' specified");
+ }
+
+ @Test
+ public void missingFileThrowsFileNotFoundException() throws Exception {
+ // act/assert
+ assertThatThrownBy(() -> new PidFile(pidFile).readPid())
+ .isInstanceOf(IllegalArgumentException.class)
+ .hasMessage("Nonexistent file '" + pidFile + "' specified");
+ }
+
+ @Test
+ public void missingFileInFullDirectoryThrowsFileNotFoundException() throws Exception {
+ // arrange
+ int[] pids = new AvailablePid().findAvailablePids(4);
+ for (int i = 1; i <= pids.length; i++) {
+ new IntegerFileWriter(new File(directory, "pid" + i + ".txt")).writeToFile(pids[i - 1]);
+ }
+ assertThat(directory.listFiles()).hasSameSizeAs(pids);
+
+ // act/assert
+ assertThatThrownBy(() -> new PidFile(directory, pidFileName).readPid())
+ .isInstanceOf(FileNotFoundException.class).hasMessage(
+ "Unable to find PID file '" + pidFileName + "' in directory '" + directory + "'");
+ }
+}
http://git-wip-us.apache.org/repos/asf/geode/blob/894f3ee7/geode-core/src/test/java/org/apache/geode/internal/process/PidFileJUnitTest.java
----------------------------------------------------------------------
diff --git a/geode-core/src/test/java/org/apache/geode/internal/process/PidFileJUnitTest.java b/geode-core/src/test/java/org/apache/geode/internal/process/PidFileJUnitTest.java
deleted file mode 100755
index 0ca73c4..0000000
--- a/geode-core/src/test/java/org/apache/geode/internal/process/PidFileJUnitTest.java
+++ /dev/null
@@ -1,275 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more contributor license
- * agreements. See the NOTICE file distributed with this work for additional information regarding
- * copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance with the License. You may obtain a
- * copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software distributed under the License
- * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
- * or implied. See the License for the specific language governing permissions and limitations under
- * the License.
- */
-package org.apache.geode.internal.process;
-
-import static org.junit.Assert.*;
-
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.FileWriter;
-import java.io.IOException;
-import java.util.concurrent.Callable;
-import java.util.concurrent.CountDownLatch;
-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.jmock.Mockery;
-import org.jmock.lib.concurrent.Synchroniser;
-import org.jmock.lib.legacy.ClassImposteriser;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.experimental.categories.Category;
-import org.junit.rules.ExpectedException;
-import org.junit.rules.TemporaryFolder;
-
-import org.apache.geode.internal.util.StopWatch;
-import org.apache.geode.test.junit.categories.IntegrationTest;
-import org.apache.geode.test.junit.rules.ExpectedTimeoutRule;
-
-/**
- * Unit tests the PidFile class.
- *
- * @since GemFire 8.2
- */
-@Category(IntegrationTest.class)
-public class PidFileJUnitTest {
-
- @Rule
- public TemporaryFolder testFolder = new TemporaryFolder();
-
- @Rule
- public ExpectedException thrown = ExpectedException.none();
-
- @Rule
- public ExpectedTimeoutRule timeout = ExpectedTimeoutRule.none();
-
- protected Mockery mockContext;
- private ExecutorService futures;
-
- @Before
- public void before() {
- mockContext = new Mockery() {
- {
- setImposteriser(ClassImposteriser.INSTANCE);
- setThreadingPolicy(new Synchroniser());
- }
- };
- this.futures = Executors.newFixedThreadPool(2);
- }
-
- @After
- public void after() {
- mockContext.assertIsSatisfied();
- assertTrue(this.futures.shutdownNow().isEmpty());
- }
-
- @Test
- public void readsIntFromFile() throws Exception {
- final File file = testFolder.newFile("my.pid");
- final String value = "42";
- writeToFile(file, value);
-
- final int readValue = new PidFile(file).readPid();
- assertEquals(Integer.parseInt(value), readValue);
- }
-
- @Test
- public void readingEmptyFileThrowsIllegalArgumentException() throws Exception {
- final File file = testFolder.newFile("my.pid");
-
- thrown.expect(IllegalArgumentException.class);
- thrown.expectMessage("Invalid pid 'null' found");
-
- new PidFile(file).readPid();
- }
-
- @Test
- public void readingFileWithNonIntegerThrowsIllegalArgumentException() throws Exception {
- final File file = testFolder.newFile("my.pid");
- final String value = "fortytwo";
- writeToFile(file, value);
-
- thrown.expect(IllegalArgumentException.class);
- thrown.expectMessage("Invalid pid '" + value + "' found");
-
- new PidFile(file).readPid();
- }
-
- @Test
- public void readingFileWithNegativeIntegerThrowsIllegalArgumentException() throws Exception {
- final File file = testFolder.newFile("my.pid");
- final String value = "-42";
- writeToFile(file, value);
-
- thrown.expect(IllegalArgumentException.class);
- thrown.expectMessage("Invalid pid '" + value + "' found");
-
- new PidFile(file).readPid();
- }
-
- @Test
- public void readingNullFileThrowsNullPointerException() throws Exception {
- final File file = null;
-
- thrown.expect(NullPointerException.class);
-
- new PidFile(file).readPid();
- }
-
- @Test
- public void timesOutReadingFromEmptyFile() throws Exception {
- final File file = testFolder.newFile("my.pid");
-
- timeout.expect(TimeoutException.class);
- timeout.expectMessage("Invalid pid 'null' found");
- timeout.expectMinimumDuration(1000);
- timeout.expectMaximumDuration(10000);
- timeout.expectTimeUnit(TimeUnit.MILLISECONDS);
-
- new PidFile(file).readPid(1500, TimeUnit.MILLISECONDS);
- }
-
- @Test
- public void readsIntBeforeTimeout() throws Exception {
- final int AWAIT_LATCH_TIMEOUT_MILLIS = 10 * 1000;
- final int OPEN_LATCH_DELAY_MILLIS = 2 * 1000;
- final int FUTURE_GET_TIMEOUT_MILLIS = 2 * 1000;
- final int READ_PID_TIMEOUT_MILLIS = 2 * OPEN_LATCH_DELAY_MILLIS;
-
- final File file = testFolder.newFile("my.pid");
- final FileWriter writer = new FileWriter(file);
-
- final CountDownLatch writePidLatch = new CountDownLatch(1);
- final String value = "42";
-
- // start Future to write the pid later but before timeout
- Future<Boolean> futureWritePid = this.futures.submit(new Callable<Boolean>() {
- @Override
- public Boolean call() throws Exception {
- writePidLatch.await(AWAIT_LATCH_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS);
- writeToFile(file, value);
- return true;
- }
- });
-
- // start Future to sleep and release the delay
- Future<Boolean> futureOpenLatch = this.futures.submit(new Callable<Boolean>() {
- @Override
- public Boolean call() throws Exception {
- Thread.sleep(OPEN_LATCH_DELAY_MILLIS);
- writePidLatch.countDown();
- return true;
- }
- });
-
- StopWatch stopWatch = new StopWatch(true);
- final int readValue = new PidFile(file).readPid(READ_PID_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS);
- assertEquals(Integer.parseInt(value), readValue);
-
- long duration = stopWatch.elapsedTimeMillis();
- assertTrue(duration > OPEN_LATCH_DELAY_MILLIS);
- assertTrue(duration < READ_PID_TIMEOUT_MILLIS);
-
- assertEquals(0, writePidLatch.getCount());
- assertTrue(futureOpenLatch.get(FUTURE_GET_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS));
- assertTrue(futureWritePid.get(FUTURE_GET_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS));
- }
-
- @Test
- public void findsCorrectFile() throws Exception {
- final File directory = testFolder.getRoot();
-
- final String fileNames[] = new String[] {"other.txt", "my.txt", "a.log", "b.log"};
- for (String fileName : fileNames) {
- testFolder.newFile(fileName);
- }
-
- final int pidValue = 42;
- final File file = testFolder.newFile("my.pid");
- writeToFile(file, String.valueOf(pidValue));
-
- final File other = testFolder.newFile("other.pid");
- writeToFile(other, "43");
-
- final File[] files = directory.listFiles();
- assertEquals(fileNames.length + 2, files.length);
-
- PidFile pidFile = new PidFile(directory, file.getName());
- assertEquals(file, pidFile.getFile());
-
- int value = pidFile.readPid();
- assertEquals(pidValue, value);
- }
-
- @Test
- public void missingFileInEmptyDirectoryThrowsFileNotFoundException() throws Exception {
- final File directory = testFolder.getRoot();
-
- final String pidFileName = "my.pid";
-
- thrown.expect(FileNotFoundException.class);
- thrown.expectMessage("Unable to find PID file '" + pidFileName + "' in directory " + directory);
-
- new PidFile(directory, pidFileName);
- }
-
- @Test
- public void missingFileThrowsFileNotFoundException() throws Exception {
- final String pidFileName = "my.pid";
-
- final File directory = testFolder.getRoot();
- final File file = new File(directory, pidFileName);
-
- thrown.expect(FileNotFoundException.class);
- thrown.expectMessage("Unable to find PID file '" + file + "'");
-
- new PidFile(file);
- }
-
- @Test
- public void missingFileInFullDirectoryThrowsFileNotFoundException() throws Exception {
- final File directory = testFolder.getRoot();
-
- final String fileNames[] = new String[] {"other.txt", "my.txt", "a.log", "b.log"};
- for (String fileName : fileNames) {
- testFolder.newFile(fileName);
- }
-
- final File other = testFolder.newFile("other.pid");
- writeToFile(other, "43");
-
- final File[] files = directory.listFiles();
- assertEquals(fileNames.length + 1, files.length);
-
- final String pidFileName = "my.pid";
-
- thrown.expect(FileNotFoundException.class);
- thrown.expectMessage("Unable to find PID file '" + pidFileName + "' in directory " + directory);
-
- new PidFile(directory, pidFileName);
- }
-
- private void writeToFile(final File file, String value) throws IOException {
- final FileWriter writer = new FileWriter(file);
- writer.write(value);
- writer.flush();
- writer.close();
- }
-}
http://git-wip-us.apache.org/repos/asf/geode/blob/894f3ee7/geode-core/src/test/java/org/apache/geode/internal/process/ProcessControllerFactoryIntegrationTest.java
----------------------------------------------------------------------
diff --git a/geode-core/src/test/java/org/apache/geode/internal/process/ProcessControllerFactoryIntegrationTest.java b/geode-core/src/test/java/org/apache/geode/internal/process/ProcessControllerFactoryIntegrationTest.java
new file mode 100644
index 0000000..aafa260
--- /dev/null
+++ b/geode-core/src/test/java/org/apache/geode/internal/process/ProcessControllerFactoryIntegrationTest.java
@@ -0,0 +1,135 @@
+/*
+ * 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.ProcessUtils.identifyPid;
+import static org.apache.geode.internal.process.ProcessUtils.isProcessAlive;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+import static org.mockito.Mockito.mock;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.contrib.java.lang.system.RestoreSystemProperties;
+import org.junit.experimental.categories.Category;
+import org.junit.rules.TemporaryFolder;
+
+import org.apache.geode.internal.process.io.IntegerFileWriter;
+import org.apache.geode.test.junit.categories.IntegrationTest;
+
+/**
+ * Functional integration tests for {@link ProcessControllerFactory}.
+ */
+@Category(IntegrationTest.class)
+public class ProcessControllerFactoryIntegrationTest {
+
+ private ProcessControllerFactory factory;
+ private ProcessControllerParameters parameters;
+ private File directory;
+ private File pidFile;
+ private String pidFileName;
+ private int pid;
+
+ @Rule
+ public RestoreSystemProperties restoreSystemProperties = new RestoreSystemProperties();
+
+ @Rule
+ public TemporaryFolder temporaryFolder = new TemporaryFolder();
+
+ @Before
+ public void before() throws Exception {
+ factory = new ProcessControllerFactory();
+ parameters = mock(ProcessControllerParameters.class);
+ directory = temporaryFolder.getRoot();
+ pidFile = new File(directory, "pid.txt");
+ pidFileName = pidFile.getName();
+ pid = identifyPid();
+
+ assertThat(pidFile).doesNotExist();
+ assertThat(isProcessAlive(pid)).isTrue();
+ }
+
+ @Test
+ public void createProcessController_withoutPidFile_throwsFileNotFoundException()
+ throws Exception {
+ // act/assert
+ assertThatThrownBy(() -> factory.createProcessController(parameters, directory, pidFileName))
+ .isInstanceOf(FileNotFoundException.class);
+ }
+
+ @Test
+ public void createProcessController_returnsMBeanProcessController() throws Exception {
+ // arrange
+ new IntegerFileWriter(pidFile).writeToFile(pid);
+
+ // act
+ ProcessController controller =
+ factory.createProcessController(parameters, directory, pidFileName);
+
+ // assert
+ assertThat(controller).isInstanceOf(MBeanProcessController.class);
+ }
+
+ @Test
+ public void createProcessController_withoutAttachAPI_returnsFileProcessController()
+ throws Exception {
+ // arrange
+ new IntegerFileWriter(pidFile).writeToFile(pid);
+ System.setProperty(ProcessControllerFactory.PROPERTY_DISABLE_ATTACH_API, "true");
+ factory = new ProcessControllerFactory();
+
+ // act
+ ProcessController controller =
+ factory.createProcessController(parameters, directory, pidFileName);
+
+ // assert
+ assertThat(controller).isInstanceOf(FileProcessController.class);
+ }
+
+ @Test
+ public void createProcessController_nullParameters_throwsNullPointerException() throws Exception {
+ // arrange
+ parameters = null;
+
+ // act/assert
+ assertThatThrownBy(() -> factory.createProcessController(parameters, directory, pidFileName))
+ .isInstanceOf(IllegalArgumentException.class);
+ }
+
+ @Test
+ public void createProcessController_nullDirectory_throwsNullPointerException() throws Exception {
+ // arrange
+ directory = null;
+
+ // act/assert
+ assertThatThrownBy(() -> factory.createProcessController(parameters, directory, pidFileName))
+ .isInstanceOf(IllegalArgumentException.class);
+ }
+
+ @Test
+ public void createProcessController_nullPidFileName_throwsNullPointerException()
+ throws Exception {
+ // arrange
+ pidFileName = null;
+
+ // act/assert
+ assertThatThrownBy(() -> factory.createProcessController(parameters, directory, pidFileName))
+ .isInstanceOf(IllegalArgumentException.class);
+ }
+}
http://git-wip-us.apache.org/repos/asf/geode/blob/894f3ee7/geode-core/src/test/java/org/apache/geode/internal/process/ProcessControllerFactoryJUnitTest.java
----------------------------------------------------------------------
diff --git a/geode-core/src/test/java/org/apache/geode/internal/process/ProcessControllerFactoryJUnitTest.java b/geode-core/src/test/java/org/apache/geode/internal/process/ProcessControllerFactoryJUnitTest.java
deleted file mode 100755
index b9c8030..0000000
--- a/geode-core/src/test/java/org/apache/geode/internal/process/ProcessControllerFactoryJUnitTest.java
+++ /dev/null
@@ -1,176 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more contributor license
- * agreements. See the NOTICE file distributed with this work for additional information regarding
- * copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance with the License. You may obtain a
- * copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software distributed under the License
- * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
- * or implied. See the License for the specific language governing permissions and limitations under
- * the License.
- */
-package org.apache.geode.internal.process;
-
-import static org.junit.Assert.*;
-
-import java.io.File;
-
-import javax.management.ObjectName;
-
-import org.junit.After;
-import org.junit.Test;
-import org.junit.experimental.categories.Category;
-
-import org.apache.geode.test.junit.categories.UnitTest;
-
-/**
- * @since GemFire 8.0
- */
-@Category(UnitTest.class)
-public class ProcessControllerFactoryJUnitTest {
-
- @After
- public void tearDown() throws Exception {
- enableAttachApi();
- }
-
- @Test
- public void testIsAttachAPIFound() throws Exception {
- validateProcessControllerFactory(true);
- disableAttachApi();
- validateProcessControllerFactory(false);
- enableAttachApi();
- validateProcessControllerFactory(true);
- }
-
- private void validateProcessControllerFactory(boolean isAttachAPIFound) throws Exception {
- final ProcessControllerFactory factory = new ProcessControllerFactory();
- assertEquals(isAttachAPIFound, factory.isAttachAPIFound());
- if (isAttachAPIFound) {
- final ProcessControllerParameters parms = new NullMBeanControllerParameters();
- final ProcessController controller =
- factory.createProcessController(parms, ProcessUtils.identifyPid());
- assertTrue(controller instanceof MBeanProcessController);
- } else {
- final ProcessControllerParameters parms = new NullFileControllerParameters();
- final ProcessController controller =
- factory.createProcessController(parms, ProcessUtils.identifyPid());
- assertTrue(controller instanceof FileProcessController);
- }
- }
-
- private static void disableAttachApi() {
- System.setProperty(ProcessControllerFactory.PROPERTY_DISABLE_ATTACH_API, "true");
- }
-
- private static void enableAttachApi() {
- System.clearProperty(ProcessControllerFactory.PROPERTY_DISABLE_ATTACH_API);
- }
-
- private static class NullMBeanControllerParameters implements ProcessControllerParameters {
- @Override
- public int getProcessId() {
- return 0;
- }
-
- @Override
- public ProcessType getProcessType() {
- return null;
- }
-
- @Override
- public ObjectName getNamePattern() {
- return null;
- }
-
- @Override
- public String getPidAttribute() {
- return null;
- }
-
- @Override
- public String getStatusMethod() {
- return null;
- }
-
- @Override
- public String getStopMethod() {
- return null;
- }
-
- @Override
- public String[] getAttributes() {
- return null;
- }
-
- @Override
- public Object[] getValues() {
- return null;
- }
-
- @Override
- public File getPidFile() {
- throw new UnsupportedOperationException("Not implemented by NullMBeanControllerParameters");
- }
-
- @Override
- public File getWorkingDirectory() {
- throw new UnsupportedOperationException("Not implemented by NullMBeanControllerParameters");
- }
- }
-
- private static class NullFileControllerParameters implements ProcessControllerParameters {
- @Override
- public int getProcessId() {
- throw new UnsupportedOperationException("Not implemented by NullFileControllerParameters");
- }
-
- @Override
- public ProcessType getProcessType() {
- throw new UnsupportedOperationException("Not implemented by NullFileControllerParameters");
- }
-
- @Override
- public ObjectName getNamePattern() {
- throw new UnsupportedOperationException("Not implemented by NullFileControllerParameters");
- }
-
- @Override
- public String getPidAttribute() {
- throw new UnsupportedOperationException("Not implemented by NullFileControllerParameters");
- }
-
- @Override
- public String getStatusMethod() {
- throw new UnsupportedOperationException("Not implemented by NullFileControllerParameters");
- }
-
- @Override
- public String getStopMethod() {
- throw new UnsupportedOperationException("Not implemented by NullFileControllerParameters");
- }
-
- @Override
- public String[] getAttributes() {
- throw new UnsupportedOperationException("Not implemented by NullFileControllerParameters");
- }
-
- @Override
- public Object[] getValues() {
- throw new UnsupportedOperationException("Not implemented by NullFileControllerParameters");
- }
-
- @Override
- public File getPidFile() {
- return null;
- }
-
- @Override
- public File getWorkingDirectory() {
- return null;
- }
- }
-}
http://git-wip-us.apache.org/repos/asf/geode/blob/894f3ee7/geode-core/src/test/java/org/apache/geode/internal/process/ProcessControllerFactoryTest.java
----------------------------------------------------------------------
diff --git a/geode-core/src/test/java/org/apache/geode/internal/process/ProcessControllerFactoryTest.java b/geode-core/src/test/java/org/apache/geode/internal/process/ProcessControllerFactoryTest.java
new file mode 100755
index 0000000..55f5d58
--- /dev/null
+++ b/geode-core/src/test/java/org/apache/geode/internal/process/ProcessControllerFactoryTest.java
@@ -0,0 +1,116 @@
+/*
+ * 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.ProcessControllerFactory.PROPERTY_DISABLE_ATTACH_API;
+import static org.apache.geode.internal.process.ProcessUtils.identifyPid;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+import static org.mockito.Mockito.mock;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.contrib.java.lang.system.RestoreSystemProperties;
+import org.junit.experimental.categories.Category;
+
+import org.apache.geode.test.junit.categories.UnitTest;
+
+/**
+ * Unit tests for {@link ProcessControllerFactory}.
+ *
+ * @since GemFire 8.0
+ */
+@Category(UnitTest.class)
+public class ProcessControllerFactoryTest {
+
+ private ProcessControllerFactory factory;
+ private ProcessControllerParameters parameters;
+ private int pid;
+
+ @Rule
+ public RestoreSystemProperties restoreSystemProperties = new RestoreSystemProperties();
+
+ @Before
+ public void before() throws Exception {
+ factory = new ProcessControllerFactory();
+ parameters = mock(ProcessControllerParameters.class);
+ pid = identifyPid();
+ }
+
+ @Test
+ public void isAttachAPIFound_withAttachAPI_returnsTrue() throws Exception {
+ // act/assert
+ assertThat(factory.isAttachAPIFound()).isTrue();
+ }
+
+ @Test
+ public void isAttachAPIFound_withoutAttachAPI_returnsFalse() throws Exception {
+ // arrange
+ System.setProperty(PROPERTY_DISABLE_ATTACH_API, "true");
+ factory = new ProcessControllerFactory();
+
+ // act/assert
+ assertThat(factory.isAttachAPIFound()).isFalse();
+ }
+
+ @Test
+ public void createProcessController_withAttachAPI_returnsMBeanProcessController()
+ throws Exception {
+ // act
+ ProcessController controller = factory.createProcessController(parameters, pid);
+
+ // assert
+ assertThat(controller).isInstanceOf(MBeanProcessController.class);
+ }
+
+ @Test
+ public void createProcessController_withoutAttachAPI_returnsFileProcessController()
+ throws Exception {
+ // arrange
+ System.setProperty(PROPERTY_DISABLE_ATTACH_API, "true");
+ factory = new ProcessControllerFactory();
+
+ // act
+ ProcessController controller = factory.createProcessController(parameters, pid);
+
+ // assert
+ assertThat(controller).isInstanceOf(FileProcessController.class);
+ }
+
+ @Test
+ public void createProcessController_withNullParameters_throwsNullPointerException()
+ throws Exception {
+ // arrange
+ parameters = null;
+
+ // act/assert
+ assertThatThrownBy(() -> factory.createProcessController(parameters, pid))
+ .isInstanceOf(IllegalArgumentException.class)
+ .hasMessageContaining("Invalid parameters 'null' specified");
+ }
+
+ @Test
+ public void createProcessController_withZeroPid_throwsIllegalArgumentException()
+ throws Exception {
+ // arrange
+ pid = 0;
+
+ // act/assert
+ assertThatThrownBy(() -> factory.createProcessController(parameters, 0))
+ .isInstanceOf(IllegalArgumentException.class)
+ .hasMessageContaining("Invalid pid '" + 0 + "' specified");
+ }
+}
http://git-wip-us.apache.org/repos/asf/geode/blob/894f3ee7/geode-core/src/test/java/org/apache/geode/internal/process/ProcessLauncherContextTest.java
----------------------------------------------------------------------
diff --git a/geode-core/src/test/java/org/apache/geode/internal/process/ProcessLauncherContextTest.java b/geode-core/src/test/java/org/apache/geode/internal/process/ProcessLauncherContextTest.java
new file mode 100644
index 0000000..c98f026
--- /dev/null
+++ b/geode-core/src/test/java/org/apache/geode/internal/process/ProcessLauncherContextTest.java
@@ -0,0 +1,208 @@
+/*
+ * 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.Collections.synchronizedList;
+import static org.apache.geode.internal.process.ProcessLauncherContext.getOverriddenDefaults;
+import static org.apache.geode.internal.process.ProcessLauncherContext.getStartupListener;
+import static org.apache.geode.internal.process.ProcessLauncherContext.isRedirectingOutput;
+import static org.apache.geode.internal.process.ProcessLauncherContext.remove;
+import static org.apache.geode.internal.process.ProcessLauncherContext.set;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+import static org.mockito.Mockito.mock;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Properties;
+
+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.UnitTest;
+
+/**
+ * Unit tests for {@link ProcessLauncherContext}.
+ */
+@Category(UnitTest.class)
+public class ProcessLauncherContextTest {
+
+ private boolean redirectOutput;
+ private Properties overriddenDefaults;
+ private StartupStatusListener startupListener;
+ private List<String> statusMessageList;
+
+ @Before
+ public void before() throws Exception {
+ redirectOutput = false;
+ overriddenDefaults = new Properties();
+ startupListener = mock(StartupStatusListener.class);
+ statusMessageList = synchronizedList(new ArrayList<>());
+ }
+
+ @After
+ public void after() throws Exception {
+ remove();
+ }
+
+ @Test
+ public void isRedirectingOutput_defaultsToFalse() throws Exception {
+ assertThat(isRedirectingOutput()).isFalse();
+ }
+
+ @Test
+ public void getOverriddenDefaults_defaultsToEmpty() throws Exception {
+ assertThat(getOverriddenDefaults()).isEmpty();
+ }
+
+ @Test
+ public void getStartupListener_defaultsToNull() throws Exception {
+ assertThat(getStartupListener()).isNull();
+ }
+
+ @Test
+ public void null_overriddenDefaults_throwsIllegalArgumentException() throws Exception {
+ // arrange
+ overriddenDefaults = null;
+
+ // act/assert
+ assertThatThrownBy(() -> set(redirectOutput, overriddenDefaults, startupListener))
+ .isInstanceOf(IllegalArgumentException.class)
+ .hasMessage("Invalid overriddenDefaults 'null' specified");
+ }
+
+ @Test
+ public void null_startupListener_isAllowed() throws Exception {
+ // arrange
+ startupListener = null;
+
+ // act
+ set(redirectOutput, overriddenDefaults, startupListener);
+
+ // assert
+ assertThat(getStartupListener()).isNull();
+ }
+
+ @Test
+ public void empty_overriddenDefaults_isAllowed() throws Exception {
+ // act
+ set(redirectOutput, overriddenDefaults, startupListener);
+
+ // assert
+ assertThat(getOverriddenDefaults()).isEmpty();
+ }
+
+ @Test
+ public void isRedirectingOutput_returnsPassedValue() throws Exception {
+ // arrange
+ redirectOutput = true;
+
+ // act
+ set(redirectOutput, overriddenDefaults, startupListener);
+
+ // assert
+ assertThat(isRedirectingOutput()).isTrue();
+ }
+
+ @Test
+ public void getOverriddenDefaults_returnsPassedInProps() throws Exception {
+ // arrange
+ overriddenDefaults.setProperty("key", "value");
+
+ // act
+ set(redirectOutput, overriddenDefaults, startupListener);
+
+ // assert
+ assertThat(getOverriddenDefaults()).hasSize(1).containsEntry("key", "value");
+ }
+
+ @Test
+ public void getStartupListener_returnsPassedInListener() throws Exception {
+ // arrange
+ overriddenDefaults.setProperty("key", "value");
+
+ // act
+ set(redirectOutput, overriddenDefaults, startupListener);
+
+ // assert
+ assertThat(getStartupListener()).isSameAs(startupListener);
+ }
+
+ @Test
+ public void remove_clearsOverriddenDefaults() throws Exception {
+ // arrange
+ overriddenDefaults.setProperty("key", "value");
+ set(false, overriddenDefaults, startupListener);
+
+ // act
+ remove();
+
+ // assert
+ assertThat(getOverriddenDefaults()).isEmpty();
+ }
+
+ @Test
+ public void remove_unsetsRedirectOutput() throws Exception {
+ // arrange
+ redirectOutput = true;
+ set(redirectOutput, overriddenDefaults, startupListener);
+
+ // act
+ remove();
+
+ // assert
+ assertThat(isRedirectingOutput()).isFalse();
+ }
+
+ @Test
+ public void remove_clearsStartupListener() throws Exception {
+ // arrange
+ startupListener = statusMessage -> statusMessageList.add(statusMessage);
+ set(redirectOutput, overriddenDefaults, startupListener);
+
+ // act
+ remove();
+
+ // assert
+ assertThat(getStartupListener()).isNull();
+ }
+
+ @Test
+ public void startupListener_installsInStartupStatus() throws Exception {
+ // arrange
+ startupListener = statusMessage -> statusMessageList.add(statusMessage);
+
+ // act
+ set(redirectOutput, overriddenDefaults, startupListener);
+
+ // assert
+ assertThat(StartupStatus.getStartupListener()).isSameAs(startupListener);
+ }
+
+ @Test
+ public void remove_uninstallsInStartupStatus() throws Exception {
+ // arrange
+ startupListener = statusMessage -> statusMessageList.add(statusMessage);
+ set(redirectOutput, overriddenDefaults, startupListener);
+
+ // act
+ remove();
+
+ // assert
+ assertThat(StartupStatus.getStartupListener()).isNull();
+ }
+}
http://git-wip-us.apache.org/repos/asf/geode/blob/894f3ee7/geode-core/src/test/java/org/apache/geode/internal/process/ProcessStreamReaderTestCase.java
----------------------------------------------------------------------
diff --git a/geode-core/src/test/java/org/apache/geode/internal/process/ProcessStreamReaderTestCase.java b/geode-core/src/test/java/org/apache/geode/internal/process/ProcessStreamReaderTestCase.java
deleted file mode 100755
index 32a7f79..0000000
--- a/geode-core/src/test/java/org/apache/geode/internal/process/ProcessStreamReaderTestCase.java
+++ /dev/null
@@ -1,254 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more contributor license
- * agreements. See the NOTICE file distributed with this work for additional information regarding
- * copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance with the License. You may obtain a
- * copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software distributed under the License
- * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
- * or implied. See the License for the specific language governing permissions and limitations under
- * the License.
- */
-package org.apache.geode.internal.process;
-
-import static org.junit.Assert.*;
-
-import java.io.File;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-import java.util.concurrent.Callable;
-
-import org.junit.After;
-import org.junit.Test;
-
-import org.apache.geode.internal.util.StopWatch;
-
-/**
- * Functional tests for ProcessStreamReader.
- *
- */
-public abstract class ProcessStreamReaderTestCase {
-
- /** Sleep timeout for {@link ProcessSleeps} instead of sleeping Long.MAX_VALUE */
- protected static final int PROCESS_FAILSAFE_TIMEOUT = 10 * 60 * 1000;
-
- /** Additional time for launched processes to live before terminating */
- protected static final int PROCESS_TIME_TO_LIVE = 3 * 500;
-
- /** Timeout to wait for a forked process to start */
- protected static final int WAIT_FOR_PROCESS_TO_START_TIMEOUT = 60 * 1000;
-
- /**
- * Timeout to wait for a running process to die -- this keeps timing out so I'm increasing it very
- * large
- */
- protected static final int WAIT_FOR_PROCESS_TO_DIE_TIMEOUT = 5 * 60 * 1000;
-
- /** Timeout to wait for a new {@link ProcessStreamReader} to be running */
- protected static final int WAIT_FOR_READER_IS_RUNNING_TIMEOUT = 20 * 1000;
-
- /** Timeout to join to a running ProcessStreamReader thread */
- protected static final int READER_JOIN_TIMEOUT = 20 * 1000;
-
- /** Brief time to sleep before repeating a conditional check */
- protected static final int INTERVAL = 20;
-
- protected Process process;
- protected ProcessStreamReader stderr;
- protected ProcessStreamReader stdout;
-
- @After
- public void stopReadersAndDestroyProcess() throws Exception {
- if (this.stderr != null) {
- this.stderr.stop();
- }
- if (this.stdout != null) {
- this.stdout.stop();
- }
- if (this.process != null) {
- this.process.destroy(); // this is async and can require more than 10 seconds in Jenkins
- /*
- * assertEventuallyFalse("Timed out destroying process after " +
- * WAIT_FOR_PROCESS_TO_DIE_TIMEOUT/(60*1000) + " minutes", new Callable<Boolean>() {
- *
- * @Override public Boolean call() throws Exception { return isAlive(process); } },
- * WAIT_FOR_PROCESS_TO_DIE_TIMEOUT, INTERVAL);
- */
- }
- }
-
- @Test
- public void processLivesAfterClosingStreams() throws Exception {
- this.process = new ProcessBuilder(createCommandLine(ProcessSleeps.class)).start();
- this.process.getErrorStream().close();
- this.process.getOutputStream().close();
- this.process.getInputStream().close();
- assertIsAlive(process);
- this.process.destroy();
- }
-
- @Test
- public void processTerminatesWhenDestroyed() throws Exception {
- this.process = new ProcessBuilder(createCommandLine(ProcessSleeps.class)).start();
- assertIsAlive(this.process);
- this.process.destroy();
- assertEventuallyFalse("Timed out destroying process", new Callable<Boolean>() {
- @Override
- public Boolean call() throws Exception {
- return isAlive(process);
- }
- }, WAIT_FOR_PROCESS_TO_DIE_TIMEOUT, INTERVAL);
- assertNotEquals(0, this.process.exitValue());
- }
-
- protected static void assertEventuallyTrue(final String message, final Callable<Boolean> callable,
- final int timeout, final int interval) throws Exception {
- boolean done = false;
- for (StopWatch time = new StopWatch(true); !done && time.elapsedTimeMillis() < timeout; done =
- (callable.call())) {
- Thread.sleep(interval);
- }
- assertTrue(message + " within timeout of " + timeout + " milliseconds", done);
- }
-
- protected static void assertEventuallyFalse(final String message,
- final Callable<Boolean> callable, final int timeout, final int interval) throws Exception {
- boolean done = false;
- for (StopWatch time = new StopWatch(true); !done && time.elapsedTimeMillis() < timeout; done =
- (!callable.call())) {
- Thread.sleep(interval);
- }
- assertTrue(message + " within timeout of " + timeout + " milliseconds", done);
- }
-
- protected static void assertIsAlive(final Process process) {
- assertTrue(isAlive(process));
- }
-
- protected static void assertIsNotAlive(final Process process) {
- assertFalse(isAlive(process));
- }
-
- protected static boolean isAlive(final Process process) {
- try {
- process.exitValue();
- return false;
- } catch (IllegalThreadStateException e) {
- return true;
- }
- }
-
- protected static String getJavaPath() {
- String java = "java";
- // if (SystemUtils.isWindows()) {
- // java = "javaw";
- // }
- return new File(new File(System.getProperty("java.home"), "bin"), java).getPath();
- }
-
- protected static String getClassPath() {
- return System.getProperty("java.class.path");
- }
-
- protected static String[] createCommandLine(final Class<?> clazz) {
- return createCommandLine(clazz, null);
- }
-
- protected static String[] createCommandLine(final Class<?> clazz, final String[] jvmArgsOpts) {
- List<String> commandLine = new ArrayList<>();
-
- commandLine.add(getJavaPath());
- commandLine.add("-server");
- commandLine.add("-classpath");
- commandLine.add(getClassPath());
-
- addJvmArgumentsAndOptions(commandLine, jvmArgsOpts);
-
- commandLine.add("-Djava.awt.headless=true");
- commandLine.add(clazz.getName());
-
- return commandLine.toArray(new String[commandLine.size()]);
- }
-
- protected static void addJvmArgumentsAndOptions(final List<String> commandLine,
- final String[] jvmArgsOpts) {
- if (jvmArgsOpts != null) {
- commandLine.addAll(Arrays.asList(jvmArgsOpts));
- }
- }
-
- protected static void assertEventuallyIsRunning(final ProcessStreamReader reader)
- throws Exception {
- assertEventuallyTrue("Waiting for ProcessStreamReader to be running", new Callable<Boolean>() {
- @Override
- public Boolean call() throws Exception {
- return reader.isRunning();
- }
- }, WAIT_FOR_READER_IS_RUNNING_TIMEOUT, INTERVAL);
- }
-
- protected static class ProcessSleeps {
- public static void main(String[] args) throws InterruptedException {
- Thread.sleep(PROCESS_FAILSAFE_TIMEOUT);
- }
- }
-
- protected static class ProcessThrowsError {
- protected static String[] LINES = new String[] {"ProcessThrowsError is starting\n",
- "ProcessThrowsError is sleeping\n", "ProcessThrowsError is throwing\n"};
- protected static String ERROR_MSG = "ProcessThrowsError throws Error";
-
- public static void main(String[] args) throws InterruptedException {
- System.err.print(LINES[0]);
- System.err.print(LINES[1]);
- Thread.sleep(PROCESS_TIME_TO_LIVE);
- System.err.print(LINES[2]);
- throw new Error(ERROR_MSG);
- }
- }
-
- protected static class ProcessPrintsToStdout {
- protected static String[] LINES = new String[] {"ProcessPrintsToStdout is starting\n",
- "ProcessPrintsToStdout is sleeping\n", "ProcessPrintsToStdout is exiting\n"};
-
- public static void main(String[] args) throws InterruptedException {
- System.out.print(LINES[0]);
- System.out.print(LINES[1]);
- Thread.sleep(PROCESS_TIME_TO_LIVE);
- System.out.print(LINES[2]);
- }
- }
-
- protected static class ProcessPrintsToStderr {
- protected static String[] LINES = new String[] {"ProcessPrintsToStdout is starting\n",
- "ProcessPrintsToStdout is sleeping\n", "ProcessPrintsToStdout is exiting\n"};
-
- public static void main(String[] args) throws InterruptedException {
- System.err.print(LINES[0]);
- System.err.print(LINES[1]);
- Thread.sleep(PROCESS_TIME_TO_LIVE);
- System.err.print(LINES[2]);
- }
- }
-
- protected static class ProcessPrintsToBoth {
- protected static String[] OUT_LINES = new String[] {"ProcessPrintsToBoth(out) is starting\n",
- "ProcessPrintsToBoth(out) is sleeping\n", "ProcessPrintsToBoth(out) is exiting\n"};
- protected static String[] ERR_LINES = new String[] {"ProcessPrintsToBoth(err) is starting\n",
- "ProcessPrintsToBoth(err) is sleeping\n", "ProcessPrintsToBoth(err) is exiting\n"};
-
- public static void main(String[] args) throws InterruptedException {
- System.out.print(OUT_LINES[0]);
- System.err.print(ERR_LINES[0]);
- System.out.print(OUT_LINES[1]);
- System.err.print(ERR_LINES[1]);
- Thread.sleep(PROCESS_TIME_TO_LIVE);
- System.out.print(OUT_LINES[2]);
- System.err.print(ERR_LINES[2]);
- }
- }
-}
http://git-wip-us.apache.org/repos/asf/geode/blob/894f3ee7/geode-core/src/test/java/org/apache/geode/internal/process/StartupStatusTest.java
----------------------------------------------------------------------
diff --git a/geode-core/src/test/java/org/apache/geode/internal/process/StartupStatusTest.java b/geode-core/src/test/java/org/apache/geode/internal/process/StartupStatusTest.java
new file mode 100644
index 0000000..04e23f3
--- /dev/null
+++ b/geode-core/src/test/java/org/apache/geode/internal/process/StartupStatusTest.java
@@ -0,0 +1,176 @@
+/*
+ * 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.Collections.synchronizedList;
+import static org.apache.geode.internal.process.StartupStatus.clearListener;
+import static org.apache.geode.internal.process.StartupStatus.getStartupListener;
+import static org.apache.geode.internal.process.StartupStatus.setListener;
+import static org.apache.geode.internal.process.StartupStatus.startup;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+import static org.mockito.Mockito.mock;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+
+import org.apache.geode.i18n.StringId;
+import org.apache.geode.test.junit.categories.UnitTest;
+
+@Category(UnitTest.class)
+public class StartupStatusTest {
+
+ private StartupStatusListener listener;
+ private List<String> statusMessageList;
+
+ @Before
+ public void before() throws Exception {
+ listener = mock(StartupStatusListener.class);
+ statusMessageList = synchronizedList(new ArrayList<>());
+ }
+
+ @After
+ public void after() throws Exception {
+ clearListener();
+ }
+
+ @Test
+ public void getStartupListener_returnsNullByDefault() throws Exception {
+ // act/assert
+ assertThat(getStartupListener()).isNull();
+ }
+
+ @Test
+ public void setListener_null_clearsStartupListener() throws Exception {
+ // arrange
+ listener = null;
+
+ // act
+ setListener(listener);
+
+ // assert
+ assertThat(getStartupListener()).isNull();
+ }
+
+ @Test
+ public void getStartupListener_returnsSetListener() throws Exception {
+ // arrange
+ setListener(listener);
+
+ // act/assert
+ assertThat(getStartupListener()).isSameAs(listener);
+ }
+
+ @Test
+ public void clearListener_doesNothingIfNull() throws Exception {
+ // arrange
+ listener = null;
+ setListener(listener);
+ assertThat(getStartupListener()).isNull();
+
+ // act
+ clearListener();
+
+ // assert
+ assertThat(getStartupListener()).isNull();
+ }
+
+ @Test
+ public void clearListener_unsetsListener() throws Exception {
+ // arrange
+ setListener(listener);
+ assertThat(getStartupListener()).isNotNull();
+
+ // act
+ clearListener();
+
+ // assert
+ assertThat(getStartupListener()).isNull();
+ }
+
+ @Test
+ public void startup_nullStringId_throwsIllegalArgumentException() throws Exception {
+ // arrange
+ StringId stringId = null;
+ Object[] params = new Object[0];
+
+ // act/assert
+ assertThatThrownBy(() -> startup(stringId, params)).isInstanceOf(IllegalArgumentException.class)
+ .hasMessage("Invalid msgId 'null' specified");
+ }
+
+ @Test
+ public void startup_emptyParams() throws Exception {
+ // arrange
+ StringId stringId = new StringId(1, "my string");
+ Object[] params = new Object[0];
+
+ // act
+ startup(stringId, params);
+
+ // assert (does not throw)
+ assertThat(getStartupListener()).isNull();
+ }
+
+ @Test
+ public void startup_doesNothingIfNoListener() throws Exception {
+ // arrange
+ StringId stringId = new StringId(1, "my string");
+ Object[] params = new Object[0];
+
+ // act
+ startup(stringId, params);
+
+ // assert (does nothing)
+ assertThat(getStartupListener()).isNull();
+ }
+
+ @Test
+ public void startup_invokesListener() throws Exception {
+ // arrange
+ listener = statusMessage -> statusMessageList.add(statusMessage);
+ StringId stringId = new StringId(1, "my string");
+ Object[] params = new Object[0];
+ setListener(listener);
+
+ // act
+ startup(stringId, params);
+
+ // assert
+ assertThat(statusMessageList).hasSize(1).contains("my string");
+ }
+
+ @Test
+ public void startupTwice_invokesListenerTwice() throws Exception {
+ // arrange
+ listener = statusMessage -> statusMessageList.add(statusMessage);
+ StringId stringIdOne = new StringId(1, "my string");
+ StringId stringIdTwo = new StringId(2, "other string");
+ Object[] params = new Object[0];
+ setListener(listener);
+
+ // act
+ startup(stringIdOne, params);
+ startup(stringIdTwo, params);
+
+ // assert
+ assertThat(statusMessageList).hasSize(2).contains("my string").contains("other string");
+ }
+}
http://git-wip-us.apache.org/repos/asf/geode/blob/894f3ee7/geode-core/src/test/java/org/apache/geode/internal/process/io/EmptyFileWriter.java
----------------------------------------------------------------------
diff --git a/geode-core/src/test/java/org/apache/geode/internal/process/io/EmptyFileWriter.java b/geode-core/src/test/java/org/apache/geode/internal/process/io/EmptyFileWriter.java
new file mode 100644
index 0000000..3acf0a6
--- /dev/null
+++ b/geode-core/src/test/java/org/apache/geode/internal/process/io/EmptyFileWriter.java
@@ -0,0 +1,40 @@
+/*
+ * 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.io;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import java.io.File;
+import java.io.IOException;
+
+/**
+ * Creates an empty file.
+ */
+public class EmptyFileWriter {
+
+ private final File file;
+
+ public EmptyFileWriter(final File file) {
+ this.file = file;
+ }
+
+ public File createNewFile() throws IOException {
+ assertThat(file).doesNotExist();
+ assertThat(file.createNewFile()).isTrue();
+ assertThat(file).exists();
+ return file;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/geode/blob/894f3ee7/geode-core/src/test/java/org/apache/geode/internal/process/io/IntegerFileReader.java
----------------------------------------------------------------------
diff --git a/geode-core/src/test/java/org/apache/geode/internal/process/io/IntegerFileReader.java b/geode-core/src/test/java/org/apache/geode/internal/process/io/IntegerFileReader.java
new file mode 100644
index 0000000..4f405bf
--- /dev/null
+++ b/geode-core/src/test/java/org/apache/geode/internal/process/io/IntegerFileReader.java
@@ -0,0 +1,38 @@
+/*
+ * 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.io;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileReader;
+import java.io.IOException;
+
+public class IntegerFileReader {
+
+ private final File file;
+
+ public IntegerFileReader(final File file) {
+ this.file = file;
+ }
+
+ public int readFromFile() throws IOException {
+ assertThat(file).exists();
+ try (BufferedReader bufferedReader = new BufferedReader(new FileReader(file))) {
+ return Integer.parseInt(bufferedReader.readLine());
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/geode/blob/894f3ee7/geode-core/src/test/java/org/apache/geode/internal/process/io/IntegerFileWriter.java
----------------------------------------------------------------------
diff --git a/geode-core/src/test/java/org/apache/geode/internal/process/io/IntegerFileWriter.java b/geode-core/src/test/java/org/apache/geode/internal/process/io/IntegerFileWriter.java
new file mode 100644
index 0000000..47f54bc
--- /dev/null
+++ b/geode-core/src/test/java/org/apache/geode/internal/process/io/IntegerFileWriter.java
@@ -0,0 +1,33 @@
+/*
+ * 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.io;
+
+import java.io.File;
+import java.io.IOException;
+
+/**
+ * Writes an integer to the file.
+ */
+public class IntegerFileWriter extends StringFileWriter {
+
+ public IntegerFileWriter(final File file) {
+ super(file);
+ }
+
+ public void writeToFile(final int pid) throws IOException {
+ writeToFile(String.valueOf(pid));
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/geode/blob/894f3ee7/geode-core/src/test/java/org/apache/geode/internal/process/io/StringFileWriter.java
----------------------------------------------------------------------
diff --git a/geode-core/src/test/java/org/apache/geode/internal/process/io/StringFileWriter.java b/geode-core/src/test/java/org/apache/geode/internal/process/io/StringFileWriter.java
new file mode 100644
index 0000000..76db475
--- /dev/null
+++ b/geode-core/src/test/java/org/apache/geode/internal/process/io/StringFileWriter.java
@@ -0,0 +1,43 @@
+/*
+ * 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.io;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+
+/**
+ * Writes a string to the file.
+ */
+public class StringFileWriter {
+
+ private final File file;
+
+ public StringFileWriter(final File file) {
+ this.file = file;
+ }
+
+ public void writeToFile(final String string) throws IOException {
+ assertThat(file).doesNotExist();
+ try (FileWriter writer = new FileWriter(file)) {
+ writer.write(string);
+ writer.flush();
+ }
+ assertThat(file).exists();
+ }
+
+}