/* * Licensed to the Apache Software Foundation (ASF) under one or more contributor license * agreements. See the NOTICE file distributed with this work for additional information regarding * copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance with the License. You may obtain a * copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express * or implied. See the License for the specific language governing permissions and limitations under * the License. */ package org.apache.geode.distributed; import static org.apache.geode.distributed.ConfigurationProperties.*; import org.apache.geode.cache.Cache; import org.apache.geode.cache.DataPolicy; import org.apache.geode.cache.Scope; import org.apache.geode.distributed.AbstractLauncher.Status; import org.apache.geode.distributed.ServerLauncher.Builder; import org.apache.geode.distributed.ServerLauncher.ServerState; import org.apache.geode.internal.AvailablePort; import org.apache.geode.internal.AvailablePortHelper; import org.apache.geode.internal.GemFireVersion; import org.apache.geode.internal.cache.AbstractCacheServer; import org.apache.geode.internal.cache.xmlcache.CacheCreation; import org.apache.geode.internal.cache.xmlcache.CacheXmlGenerator; import org.apache.geode.internal.cache.xmlcache.RegionAttributesCreation; import org.apache.geode.internal.net.SocketCreatorFactory; import org.apache.geode.internal.process.ProcessControllerFactory; import org.apache.geode.internal.process.ProcessType; import org.apache.geode.internal.process.ProcessUtils; import org.apache.geode.internal.security.SecurableCommunicationChannel; import org.apache.geode.test.junit.categories.IntegrationTest; import org.junit.After; import org.junit.Before; import org.junit.Ignore; import org.junit.Test; import org.junit.experimental.categories.Category; import java.io.File; import java.io.FileWriter; import java.io.PrintWriter; import java.lang.management.ManagementFactory; import java.net.BindException; import java.net.InetAddress; import static org.apache.geode.distributed.ConfigurationProperties.MCAST_PORT; import static org.hamcrest.CoreMatchers.equalTo; import static org.hamcrest.CoreMatchers.is; import static org.junit.Assert.*; /** * Integration tests for ServerLauncher as a local API in the local JVM. * * @see org.apache.geode.distributed.AbstractLauncher * @see org.apache.geode.distributed.ServerLauncher * @see org.apache.geode.distributed.ServerLauncher.Builder * @see org.apache.geode.distributed.ServerLauncher.ServerState * @see org.apache.geode.internal.AvailablePortHelper * @since GemFire 8.0 */ @Category(IntegrationTest.class) public class ServerLauncherLocalIntegrationTest extends AbstractServerLauncherIntegrationTestCase { @Before public final void setUpServerLauncherLocalTest() throws Exception { disconnectFromDS(); System.setProperty(ProcessType.TEST_PREFIX_PROPERTY, getUniqueName() + "-"); } @After public final void tearDownServerLauncherLocalTest() throws Exception { disconnectFromDS(); } protected Status getExpectedStopStatusForNotRunning() { return Status.NOT_RESPONDING; } @Test public void testBuilderSetProperties() throws Throwable { String rootFolder = this.temporaryFolder.getRoot().getCanonicalPath(); this.launcher = new Builder().setDisableDefaultServer(true).setForce(true) .setMemberName(getUniqueName()).setWorkingDirectory(rootFolder) .set(DISABLE_AUTO_RECONNECT, "true").set(LOG_LEVEL, "config").set(MCAST_PORT, "0").build(); assertNotNull(this.launcher); try { assertEquals(Status.ONLINE, this.launcher.start().getStatus()); waitForServerToStart(this.launcher); final Cache cache = this.launcher.getCache(); assertNotNull(cache); final DistributedSystem distributedSystem = cache.getDistributedSystem(); assertNotNull(distributedSystem); assertEquals("true", distributedSystem.getProperties().getProperty(DISABLE_AUTO_RECONNECT)); assertEquals("config", distributedSystem.getProperties().getProperty(LOG_LEVEL)); assertEquals("0", distributedSystem.getProperties().getProperty(MCAST_PORT)); assertEquals(getUniqueName(), distributedSystem.getProperties().getProperty(NAME)); } catch (Throwable e) { this.errorCollector.addError(e); } try { assertEquals(Status.STOPPED, this.launcher.stop().getStatus()); assertNull(this.launcher.getCache()); } catch (Throwable e) { this.errorCollector.addError(e); } } @Test public void testIsAttachAPIFound() throws Exception { final ProcessControllerFactory factory = new ProcessControllerFactory(); assertTrue(factory.isAttachAPIFound()); } @Test public void testStartCreatesPidFile() throws Throwable { String rootFolder = this.temporaryFolder.getRoot().getCanonicalPath(); // build and start the Server locally final Builder builder = new Builder().setDisableDefaultServer(true) .setMemberName(getUniqueName()).setRedirectOutput(true).setWorkingDirectory(rootFolder) .set(LOG_LEVEL, "config").set(MCAST_PORT, "0"); this.launcher = builder.build(); assertNotNull(this.launcher); try { this.launcher.start(); waitForServerToStart(this.launcher); assertEquals(Status.ONLINE, this.launcher.status().getStatus()); // validate the pid file and its contents this.pidFile = new File(this.temporaryFolder.getRoot(), ProcessType.SERVER.getPidFileName()); assertTrue(this.pidFile.exists()); final int pid = readPid(this.pidFile); assertTrue(pid > 0); assertTrue(ProcessUtils.isProcessAlive(pid)); assertEquals(getPid(), pid); assertEquals(Status.ONLINE, this.launcher.status().getStatus()); } catch (Throwable e) { this.errorCollector.addError(e); } try { assertEquals(Status.STOPPED, this.launcher.stop().getStatus()); waitForFileToDelete(this.pidFile); } catch (Throwable e) { this.errorCollector.addError(e); } } @Test public void testStartDeletesStaleControlFiles() throws Throwable { String rootFolder = this.temporaryFolder.getRoot().getCanonicalPath(); // create existing control files this.stopRequestFile = new File(this.temporaryFolder.getRoot(), ProcessType.SERVER.getStopRequestFileName()); this.stopRequestFile.createNewFile(); assertTrue(this.stopRequestFile.exists()); this.statusRequestFile = new File(this.temporaryFolder.getRoot(), ProcessType.SERVER.getStatusRequestFileName()); this.statusRequestFile.createNewFile(); assertTrue(this.statusRequestFile.exists()); this.statusFile = new File(this.temporaryFolder.getRoot(), ProcessType.SERVER.getStatusFileName()); this.statusFile.createNewFile(); assertTrue(this.statusFile.exists()); // build and start the server final Builder builder = new Builder().setDisableDefaultServer(true) .setMemberName(getUniqueName()).setRedirectOutput(true).setWorkingDirectory(rootFolder) .set(LOG_LEVEL, "config").set(MCAST_PORT, "0"); assertFalse(builder.getForce()); this.launcher = builder.build(); assertFalse(this.launcher.isForcing()); this.launcher.start(); try { waitForServerToStart(this.launcher); } catch (Throwable e) { this.errorCollector.addError(e); } try { // validate the pid file and its contents this.pidFile = new File(this.temporaryFolder.getRoot(), ProcessType.SERVER.getPidFileName()); assertTrue(this.pidFile.exists()); final int pid = readPid(this.pidFile); assertTrue(pid > 0); assertTrue(ProcessUtils.isProcessAlive(pid)); assertEquals(getPid(), pid); // validate stale control files were deleted assertFalse(this.stopRequestFile.exists()); assertFalse(this.statusRequestFile.exists()); assertFalse(this.statusFile.exists()); } catch (Throwable e) { this.errorCollector.addError(e); } try { assertEquals(Status.STOPPED, this.launcher.stop().getStatus()); waitForFileToDelete(this.pidFile); } catch (Throwable e) { this.errorCollector.addError(e); } } @Test public void testStartOverwritesStalePidFile() throws Throwable { String rootFolder = this.temporaryFolder.getRoot().getCanonicalPath(); // create existing pid file this.pidFile = new File(this.temporaryFolder.getRoot(), ProcessType.SERVER.getPidFileName()); assertFalse("Integer.MAX_VALUE shouldn't be the same as local pid " + Integer.MAX_VALUE, Integer.MAX_VALUE == ProcessUtils.identifyPid()); writePid(this.pidFile, Integer.MAX_VALUE); // build and start the server final Builder builder = new Builder().setDisableDefaultServer(true) .setMemberName(getUniqueName()).setRedirectOutput(true).setWorkingDirectory(rootFolder) .set(LOG_LEVEL, "config").set(MCAST_PORT, "0"); assertFalse(builder.getForce()); this.launcher = builder.build(); assertFalse(this.launcher.isForcing()); this.launcher.start(); try { waitForServerToStart(this.launcher); } catch (Throwable e) { this.errorCollector.addError(e); } try { // validate the pid file and its contents assertTrue(this.pidFile.exists()); final int pid = readPid(this.pidFile); assertTrue(pid > 0); assertTrue(ProcessUtils.isProcessAlive(pid)); assertEquals(getPid(), pid); } catch (Throwable e) { this.errorCollector.addError(e); } try { assertEquals(Status.STOPPED, this.launcher.stop().getStatus()); waitForFileToDelete(this.pidFile); } catch (Throwable e) { this.errorCollector.addError(e); } } /** * Confirms fix for #47778. */ @Test public void testStartUsingDisableDefaultServerLeavesPortFree() throws Throwable { String rootFolder = this.temporaryFolder.getRoot().getCanonicalPath(); // build and start the server assertTrue(AvailablePort.isPortAvailable(this.serverPort, AvailablePort.SOCKET)); // build and start the server final Builder builder = new Builder().setDisableDefaultServer(true) .setMemberName(getUniqueName()).setRedirectOutput(true).setWorkingDirectory(rootFolder) .set(LOG_LEVEL, "config").set(MCAST_PORT, "0"); this.launcher = builder.build(); // wait for server to start try { // if start succeeds without throwing exception then #47778 is fixed this.launcher.start(); waitForServerToStart(this.launcher); // validate the pid file and its contents this.pidFile = new File(this.temporaryFolder.getRoot(), ProcessType.SERVER.getPidFileName()); assertTrue(this.pidFile.exists()); int pid = readPid(this.pidFile); assertTrue(pid > 0); assertTrue(ProcessUtils.isProcessAlive(pid)); assertEquals(getPid(), pid); // verify server did not a port assertTrue(AvailablePort.isPortAvailable(this.serverPort, AvailablePort.SOCKET)); final ServerState status = this.launcher.status(); final String portString = status.getPort(); assertEquals("Port should be \"\" instead of " + portString, "", portString); } catch (Throwable e) { this.errorCollector.addError(e); } // stop the server try { assertEquals(Status.STOPPED, this.launcher.stop().getStatus()); waitForFileToDelete(this.pidFile); } catch (Throwable e) { this.errorCollector.addError(e); } } /** * Confirms fix for #47778. */ @Test public void testStartUsingDisableDefaultServerSkipsPortCheck() throws Throwable { String rootFolder = this.temporaryFolder.getRoot().getCanonicalPath(); // generate one free port and then use TEST_OVERRIDE_DEFAULT_PORT_PROPERTY this.socket = SocketCreatorFactory .createNonDefaultInstance(false, false, null, null, System.getProperties()) .createServerSocket(this.serverPort, 50, null, -1); assertFalse(AvailablePort.isPortAvailable(this.serverPort, AvailablePort.SOCKET)); // build and start the server final Builder builder = new Builder().setDisableDefaultServer(true) .setMemberName(getUniqueName()).setRedirectOutput(true).setWorkingDirectory(rootFolder) .set(LOG_LEVEL, "config").set(MCAST_PORT, "0"); this.launcher = builder.build(); // wait for server to start try { // if start succeeds without throwing exception then #47778 is fixed this.launcher.start(); waitForServerToStart(this.launcher); // validate the pid file and its contents this.pidFile = new File(this.temporaryFolder.getRoot(), ProcessType.SERVER.getPidFileName()); assertTrue(this.pidFile.exists()); int pid = readPid(this.pidFile); assertTrue(pid > 0); assertTrue(ProcessUtils.isProcessAlive(pid)); assertEquals(getPid(), pid); final ServerState status = this.launcher.status(); final String portString = status.getPort(); assertEquals("Port should be \"\" instead of " + portString, "", portString); } catch (Throwable e) { this.errorCollector.addError(e); } // stop the server try { assertEquals(Status.STOPPED, this.launcher.stop().getStatus()); waitForFileToDelete(this.pidFile); } catch (Throwable e) { this.errorCollector.addError(e); } // verify port is still in use this.errorCollector.checkThat( AvailablePort.isPortAvailable(this.serverPort, AvailablePort.SOCKET), is(equalTo(false))); } @Test @Ignore("Need to rewrite this without using dunit.Host") public void testStartUsingForceOverwritesExistingPidFile() throws Throwable {}/* * assertTrue(getUniqueName() + " is broken if PID == Integer.MAX_VALUE", * ProcessUtils.identifyPid() != Integer.MAX_VALUE); * * // create existing pid file this.pidFile = new * File(ProcessType.SERVER.getPidFileName()); final int realPid = * Host.getHost(0).getVM(3).invoke(() -> ProcessUtils.identifyPid()); * assertFalse(realPid == ProcessUtils.identifyPid()); * writePid(this.pidFile, realPid); * * // build and start the server final Builder builder = new Builder() * .setDisableDefaultServer(true) .setForce(true) * .setMemberName(getUniqueName()) .setRedirectOutput(true) * .set(DistributionConfig.ConfigurationProperties.MCAST_PORT, "0"); * * assertTrue(builder.getForce()); this.launcher = builder.build(); * assertTrue(this.launcher.isForcing()); this.launcher.start(); * * // collect and throw the FIRST failure Throwable failure = null; * * try { waitForServerToStart(this.launcher); * * // validate the pid file and its contents * assertTrue(this.pidFile.exists()); final int pid = * readPid(this.pidFile); assertTrue(pid > 0); * assertTrue(ProcessUtils.isProcessAlive(pid)); * assertIndexDetailsEquals(getPid(), pid); * * // validate log file was created final String logFileName = * getUniqueName()+".log"; assertTrue("Log file should exist: " + * logFileName, new File(logFileName).exists()); * * } catch (Throwable e) { logger.error(e); if (failure == null) { failure * = e; } } * * try { assertIndexDetailsEquals(Status.STOPPED, * this.launcher.stop().getStatus()); waitForFileToDelete(this.pidFile); } * catch (Throwable e) { logger.error(e); if (failure == null) { failure = * e; } } * * if (failure != null) { throw failure; } } // * testStartUsingForceOverwritesExistingPidFile */ /** * Confirms part of fix for #47664 */ @Test public void testStartUsingServerPortOverridesCacheXml() throws Throwable { // verifies part of the fix for #47664 String rootFolder = this.temporaryFolder.getRoot().getCanonicalPath(); // generate two free ports final int[] freeTCPPorts = AvailablePortHelper.getRandomAvailableTCPPorts(2); assertTrue(AvailablePort.isPortAvailable(freeTCPPorts[0], AvailablePort.SOCKET)); assertTrue(AvailablePort.isPortAvailable(freeTCPPorts[1], AvailablePort.SOCKET)); // write out cache.xml with one port final CacheCreation creation = new CacheCreation(); final RegionAttributesCreation attrs = new RegionAttributesCreation(creation); attrs.setScope(Scope.DISTRIBUTED_ACK); attrs.setDataPolicy(DataPolicy.REPLICATE); creation.createRegion(getUniqueName(), attrs); creation.addCacheServer().setPort(freeTCPPorts[0]); File cacheXmlFile = this.temporaryFolder.newFile(getUniqueName() + ".xml"); final PrintWriter pw = new PrintWriter(new FileWriter(cacheXmlFile), true); CacheXmlGenerator.generate(creation, pw); pw.close(); System.setProperty(CACHE_XML_FILE, cacheXmlFile.getCanonicalPath()); // start server final Builder builder = new Builder().setMemberName(getUniqueName()).setRedirectOutput(true) .setServerPort(freeTCPPorts[1]).setWorkingDirectory(rootFolder).set(LOG_LEVEL, "config") .set(MCAST_PORT, "0"); this.launcher = builder.build(); this.launcher.start(); // wait for server to start up try { waitForServerToStart(this.launcher); // validate the pid file and its contents this.pidFile = new File(this.temporaryFolder.getRoot(), ProcessType.SERVER.getPidFileName()); assertTrue(this.pidFile.exists()); int pid = readPid(this.pidFile); assertTrue(pid > 0); assertTrue(ProcessUtils.isProcessAlive(pid)); assertEquals(getPid(), pid); // verify server used --server-port instead of default or port in cache.xml assertTrue(AvailablePort.isPortAvailable(freeTCPPorts[0], AvailablePort.SOCKET)); assertFalse(AvailablePort.isPortAvailable(freeTCPPorts[1], AvailablePort.SOCKET)); final ServerState status = this.launcher.status(); final String portString = status.getPort(); final int port = Integer.valueOf(portString); assertEquals("Port should be " + freeTCPPorts[1] + " instead of " + port, freeTCPPorts[1], port); } catch (Throwable e) { this.errorCollector.addError(e); } // stop the server try { assertEquals(Status.STOPPED, this.launcher.stop().getStatus()); waitForFileToDelete(this.pidFile); assertFalse("PID file still exists!", pidFile.exists()); } catch (Throwable e) { this.errorCollector.addError(e); } } /** * Confirms part of fix for #47664 */ @Test public void testStartUsingServerPortUsedInsteadOfDefaultCacheXml() throws Throwable { String rootFolder = this.temporaryFolder.getRoot().getCanonicalPath(); // write out cache.xml with one port final CacheCreation creation = new CacheCreation(); final RegionAttributesCreation attrs = new RegionAttributesCreation(creation); attrs.setScope(Scope.DISTRIBUTED_ACK); attrs.setDataPolicy(DataPolicy.REPLICATE); creation.createRegion(getUniqueName(), attrs); creation.addCacheServer(); File cacheXmlFile = this.temporaryFolder.newFile(getUniqueName() + ".xml"); final PrintWriter pw = new PrintWriter(new FileWriter(cacheXmlFile), true); CacheXmlGenerator.generate(creation, pw); pw.close(); System.setProperty(CACHE_XML_FILE, cacheXmlFile.getCanonicalPath()); // start server final Builder builder = new Builder().setMemberName(getUniqueName()).setRedirectOutput(true) .setServerPort(this.serverPort).setWorkingDirectory(rootFolder).set(LOG_LEVEL, "config") .set(MCAST_PORT, "0"); this.launcher = builder.build(); this.launcher.start(); // wait for server to start up try { waitForServerToStart(this.launcher); // validate the pid file and its contents this.pidFile = new File(this.temporaryFolder.getRoot(), ProcessType.SERVER.getPidFileName()); assertTrue(this.pidFile.exists()); int pid = readPid(this.pidFile); assertTrue(pid > 0); assertTrue(ProcessUtils.isProcessAlive(pid)); assertEquals(getPid(), pid); // verify server used --server-port instead of default assertFalse(AvailablePort.isPortAvailable(this.serverPort, AvailablePort.SOCKET)); final int port = Integer.valueOf(this.launcher.status().getPort()); assertEquals("Port should be " + this.serverPort + " instead of " + port, this.serverPort, port); } catch (Throwable e) { this.errorCollector.addError(e); } // stop the server try { assertEquals(Status.STOPPED, this.launcher.stop().getStatus()); waitForFileToDelete(this.pidFile); } catch (Throwable e) { this.errorCollector.addError(e); } } @Test public void testStartWithDefaultPortInUseFails() throws Throwable { String rootFolder = this.temporaryFolder.getRoot().getCanonicalPath(); // generate one free port and then use TEST_OVERRIDE_DEFAULT_PORT_PROPERTY this.socket = SocketCreatorFactory.getSocketCreatorForComponent(SecurableCommunicationChannel.CLUSTER) .createServerSocket(this.serverPort, 50, null, -1); assertFalse(AvailablePort.isPortAvailable(this.serverPort, AvailablePort.SOCKET)); // build and start the server final Builder builder = new Builder().setMemberName(getUniqueName()).setRedirectOutput(true) .setWorkingDirectory(rootFolder).set(LOG_LEVEL, "config").set(MCAST_PORT, "0"); this.launcher = builder.build(); RuntimeException expected = null; try { this.launcher.start(); // why did it not fail like it's supposed to? final String property = System.getProperty(AbstractCacheServer.TEST_OVERRIDE_DEFAULT_PORT_PROPERTY); assertNotNull(property); assertEquals(this.serverPort, Integer.valueOf(property).intValue()); assertFalse(AvailablePort.isPortAvailable(this.serverPort, AvailablePort.SOCKET)); fail("Server port is " + this.launcher.getCache().getCacheServers().get(0).getPort()); fail("ServerLauncher start should have thrown RuntimeException caused by BindException"); } catch (RuntimeException e) { expected = e; assertNotNull(expected.getMessage()); // BindException text varies by platform } catch (Throwable e) { this.errorCollector.addError(e); } try { assertNotNull(expected); final Throwable cause = expected.getCause(); assertNotNull(cause); assertTrue(cause instanceof BindException); // BindException string varies by platform } catch (Throwable e) { this.errorCollector.addError(e); } try { this.pidFile = new File(this.temporaryFolder.getRoot(), ProcessType.SERVER.getPidFileName()); assertFalse("Pid file should not exist: " + this.pidFile, this.pidFile.exists()); // creation of log file seems to be random -- look into why sometime final String logFileName = getUniqueName() + ".log"; assertFalse("Log file should not exist: " + logFileName, new File(this.temporaryFolder.getRoot(), logFileName).exists()); } catch (Throwable e) { this.errorCollector.addError(e); } // just in case the launcher started... ServerState status = null; try { status = this.launcher.stop(); } catch (Throwable t) { // ignore } try { waitForFileToDelete(this.pidFile); assertEquals(getExpectedStopStatusForNotRunning(), status.getStatus()); } catch (Throwable e) { this.errorCollector.addError(e); } } @Test @Ignore("Need to rewrite this without using dunit.Host") public void testStartWithExistingPidFileFails() throws Throwable {}/* * // create existing pid file final int realPid = * Host.getHost(0).getVM(3).invoke(() -> ProcessUtils.identifyPid()); * assertFalse("Remote pid shouldn't be the same as local pid " + realPid, * realPid == ProcessUtils.identifyPid()); * * this.pidFile = new File(ProcessType.SERVER.getPidFileName()); * writePid(this.pidFile, realPid); * * // build and start the server final Builder builder = new Builder() * .setDisableDefaultServer(true) .setMemberName(getUniqueName()) * .setRedirectOutput(true) .set(logLevel, "config") * .set(DistributionConfig.ConfigurationProperties.MCAST_PORT, "0"); * * assertFalse(builder.getForce()); this.launcher = builder.build(); * assertFalse(this.launcher.isForcing()); * * // collect and throw the FIRST failure Throwable failure = null; * RuntimeException expected = null; * * try { this.launcher.start(); * fail("ServerLauncher start should have thrown RuntimeException caused by FileAlreadyExistsException" * ); } catch (RuntimeException e) { expected = e; * assertNotNull(expected.getMessage()); assertTrue(expected.getMessage(). * contains("A PID file already exists and a Server may be running in")); } * catch (Throwable e) { logger.error(e); if (failure == null) { failure = * e; } } * * // just in case the launcher started... ServerState status = null; try { * status = this.launcher.stop(); } catch (Throwable t) { // ignore } * * try { assertNotNull(expected); final Throwable cause = * expected.getCause(); assertNotNull(cause); assertTrue(cause instanceof * FileAlreadyExistsException); * assertTrue(cause.getMessage().contains("Pid file already exists: ")); * assertTrue(cause.getMessage().contains("vf.gf.server.pid for process " + * realPid)); } catch (Throwable e) { logger.error(e); if (failure == null) * { failure = e; } } * * try { delete(this.pidFile); final Status theStatus = status.getStatus(); * assertFalse(theStatus == Status.STARTING); assertFalse(theStatus == * Status.ONLINE); } catch (Throwable e) { logger.error(e); if (failure == * null) { failure = e; } } * * if (failure != null) { throw failure; } } // * testStartWithExistingPidFileFails */ /** * Confirms fix for #47665. */ @Test public void testStartUsingServerPortInUseFails() throws Throwable { String rootFolder = this.temporaryFolder.getRoot().getCanonicalPath(); // generate one free port and then use TEST_OVERRIDE_DEFAULT_PORT_PROPERTY final int freeTCPPort = AvailablePort.getRandomAvailablePort(AvailablePort.SOCKET); this.socket = SocketCreatorFactory.getSocketCreatorForComponent(SecurableCommunicationChannel.CLUSTER) .createServerSocket(freeTCPPort, 50, null, -1); // build and start the server final Builder builder = new Builder().setMemberName(getUniqueName()).setRedirectOutput(true) .setServerPort(freeTCPPort).setWorkingDirectory(rootFolder).set(LOG_LEVEL, "config") .set(MCAST_PORT, "0"); this.launcher = builder.build(); RuntimeException expected = null; try { this.launcher.start(); fail("ServerLauncher start should have thrown RuntimeException caused by BindException"); } catch (RuntimeException e) { expected = e; assertNotNull(expected.getMessage()); // BindException string varies by platform } catch (Throwable e) { this.errorCollector.addError(e); } try { assertNotNull(expected); final Throwable cause = expected.getCause(); assertNotNull(cause); assertTrue(cause instanceof BindException); // BindException string varies by platform } catch (Throwable e) { this.errorCollector.addError(e); } try { this.pidFile = new File(this.temporaryFolder.getRoot(), ProcessType.SERVER.getPidFileName()); assertFalse("Pid file should not exist: " + this.pidFile, this.pidFile.exists()); } catch (Throwable e) { this.errorCollector.addError(e); } // just in case the launcher started... ServerState status = null; try { status = this.launcher.stop(); } catch (Throwable t) { // ignore } try { waitForFileToDelete(this.pidFile); assertEquals(getExpectedStopStatusForNotRunning(), status.getStatus()); } catch (Throwable e) { this.errorCollector.addError(e); } } @Test public void testStatusUsingPid() throws Throwable { String rootFolder = this.temporaryFolder.getRoot().getCanonicalPath(); // build and start the server final Builder builder = new Builder().setDisableDefaultServer(true) .setMemberName(getUniqueName()).setRedirectOutput(true).setWorkingDirectory(rootFolder) .set(LOG_LEVEL, "config").set(MCAST_PORT, "0"); assertFalse(builder.getForce()); this.launcher = builder.build(); assertFalse(this.launcher.isForcing()); ServerLauncher pidLauncher = null; try { this.launcher.start(); waitForServerToStart(this.launcher); this.pidFile = new File(this.temporaryFolder.getRoot(), ProcessType.SERVER.getPidFileName()); assertTrue(this.pidFile.exists()); final int pid = readPid(this.pidFile); assertTrue(pid > 0); assertEquals(ProcessUtils.identifyPid(), pid); pidLauncher = new Builder().setPid(pid).build(); assertNotNull(pidLauncher); assertFalse(pidLauncher.isRunning()); final ServerState actualStatus = pidLauncher.status(); assertNotNull(actualStatus); assertEquals(Status.ONLINE, actualStatus.getStatus()); assertEquals(pid, actualStatus.getPid().intValue()); assertTrue(actualStatus.getUptime() > 0); // getWorkingDirectory returns user.dir instead of rootFolder because test is starting Server // in this process (to move logFile and pidFile into temp dir) assertEquals(ManagementFactory.getRuntimeMXBean().getClassPath(), actualStatus.getClasspath()); assertEquals(GemFireVersion.getGemFireVersion(), actualStatus.getGemFireVersion()); assertEquals(System.getProperty("java.version"), actualStatus.getJavaVersion()); assertEquals(InetAddress.getLocalHost().getCanonicalHostName(), actualStatus.getHost()); assertEquals(getUniqueName(), actualStatus.getMemberName()); } catch (Throwable e) { this.errorCollector.addError(e); } if (pidLauncher == null) { try { assertEquals(Status.STOPPED, this.launcher.stop().getStatus()); waitForFileToDelete(this.pidFile); } catch (Throwable e) { this.errorCollector.addError(e); } } else { try { assertEquals(Status.STOPPED, pidLauncher.stop().getStatus()); waitForFileToDelete(this.pidFile); } catch (Throwable e) { this.errorCollector.addError(e); } } } @Test public void testStatusUsingWorkingDirectory() throws Throwable { String rootFolder = this.temporaryFolder.getRoot().getCanonicalPath(); // build and start the server final Builder builder = new Builder().setDisableDefaultServer(true) .setMemberName(getUniqueName()).setRedirectOutput(true).setWorkingDirectory(rootFolder) .set(LOG_LEVEL, "config").set(MCAST_PORT, "0"); assertFalse(builder.getForce()); this.launcher = builder.build(); assertFalse(this.launcher.isForcing()); ServerLauncher dirLauncher = null; try { this.launcher.start(); waitForServerToStart(this.launcher); this.pidFile = new File(this.temporaryFolder.getRoot(), ProcessType.SERVER.getPidFileName()); assertTrue(this.pidFile.exists()); final int pid = readPid(this.pidFile); assertTrue(pid > 0); assertEquals(ProcessUtils.identifyPid(), pid); dirLauncher = new Builder().setWorkingDirectory(rootFolder).build(); assertNotNull(dirLauncher); assertFalse(dirLauncher.isRunning()); final ServerState actualStatus = dirLauncher.status(); assertNotNull(actualStatus); assertEquals(Status.ONLINE, actualStatus.getStatus()); assertEquals(pid, actualStatus.getPid().intValue()); assertTrue(actualStatus.getUptime() > 0); // getWorkingDirectory returns user.dir instead of rootFolder because test is starting Server // in this process (to move logFile and pidFile into temp dir) assertEquals(ManagementFactory.getRuntimeMXBean().getClassPath(), actualStatus.getClasspath()); assertEquals(GemFireVersion.getGemFireVersion(), actualStatus.getGemFireVersion()); assertEquals(System.getProperty("java.version"), actualStatus.getJavaVersion()); assertEquals(InetAddress.getLocalHost().getCanonicalHostName(), actualStatus.getHost()); assertEquals(getUniqueName(), actualStatus.getMemberName()); } catch (Throwable e) { this.errorCollector.addError(e); } if (dirLauncher == null) { try { assertEquals(Status.STOPPED, this.launcher.stop().getStatus()); waitForFileToDelete(this.pidFile); } catch (Throwable e) { this.errorCollector.addError(e); } } else { try { assertEquals(Status.STOPPED, dirLauncher.stop().getStatus()); waitForFileToDelete(this.pidFile); } catch (Throwable e) { this.errorCollector.addError(e); } } } @Test public void testStopUsingPid() throws Throwable { String rootFolder = this.temporaryFolder.getRoot().getCanonicalPath(); // build and start the server final Builder builder = new Builder().setDisableDefaultServer(true) .setMemberName(getUniqueName()).setRedirectOutput(true).setWorkingDirectory(rootFolder) .set(LOG_LEVEL, "config").set(MCAST_PORT, "0"); assertFalse(builder.getForce()); this.launcher = builder.build(); assertFalse(this.launcher.isForcing()); ServerLauncher pidLauncher = null; try { this.launcher.start(); waitForServerToStart(this.launcher); // validate the pid file and its contents this.pidFile = new File(this.temporaryFolder.getRoot(), ProcessType.SERVER.getPidFileName()); assertTrue(this.pidFile.exists()); final int pid = readPid(this.pidFile); assertTrue(pid > 0); assertEquals(ProcessUtils.identifyPid(), pid); pidLauncher = new Builder().setPid(pid).build(); assertNotNull(pidLauncher); assertFalse(pidLauncher.isRunning()); // stop the server final ServerState serverState = pidLauncher.stop(); assertNotNull(serverState); assertEquals(Status.STOPPED, serverState.getStatus()); } catch (Throwable e) { this.errorCollector.addError(e); } try { this.launcher.stop(); } catch (Throwable e) { // ignore } try { // verify the PID file was deleted waitForFileToDelete(this.pidFile); } catch (Throwable e) { this.errorCollector.addError(e); } } @Test public void testStopUsingWorkingDirectory() throws Throwable { String rootFolder = this.temporaryFolder.getRoot().getCanonicalPath(); // build and start the server final Builder builder = new Builder().setDisableDefaultServer(true) .setMemberName(getUniqueName()).setRedirectOutput(true).setWorkingDirectory(rootFolder) .set(LOG_LEVEL, "config").set(MCAST_PORT, "0"); assertFalse(builder.getForce()); this.launcher = builder.build(); assertFalse(this.launcher.isForcing()); ServerLauncher dirLauncher = null; try { this.launcher.start(); waitForServerToStart(this.launcher); // validate the pid file and its contents this.pidFile = new File(this.temporaryFolder.getRoot(), ProcessType.SERVER.getPidFileName()); assertTrue(this.pidFile.exists()); final int pid = readPid(this.pidFile); assertTrue(pid > 0); assertEquals(ProcessUtils.identifyPid(), pid); dirLauncher = new Builder().setWorkingDirectory(rootFolder).build(); assertNotNull(dirLauncher); assertFalse(dirLauncher.isRunning()); // stop the server final ServerState serverState = dirLauncher.stop(); assertNotNull(serverState); assertEquals(Status.STOPPED, serverState.getStatus()); } catch (Throwable e) { this.errorCollector.addError(e); } try { this.launcher.stop(); } catch (Throwable e) { // ignore } try { // verify the PID file was deleted waitForFileToDelete(this.pidFile); } catch (Throwable e) { this.errorCollector.addError(e); } } }