/*
* 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.management.internal.cli.commands;
import static org.apache.geode.distributed.ConfigurationProperties.*;
import static org.apache.geode.test.dunit.Assert.*;
import static org.apache.geode.test.dunit.Wait.*;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.lang.management.ManagementFactory;
import java.net.InetAddress;
import java.nio.charset.Charset;
import java.text.DateFormat;
import java.text.MessageFormat;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Queue;
import java.util.Set;
import java.util.concurrent.ConcurrentLinkedDeque;
import java.util.concurrent.TimeUnit;
import javax.management.MBeanServerConnection;
import javax.management.ObjectName;
import javax.management.Query;
import javax.management.QueryExp;
import javax.management.remote.JMXConnector;
import javax.management.remote.JMXConnectorFactory;
import javax.management.remote.JMXServiceURL;
import org.junit.FixMethodOrder;
import org.junit.Test;
import org.junit.experimental.categories.Category;
import org.junit.runners.MethodSorters;
import org.apache.geode.cache.Region;
import org.apache.geode.cache.client.ClientCache;
import org.apache.geode.cache.client.ClientCacheFactory;
import org.apache.geode.cache.client.ClientRegionFactory;
import org.apache.geode.cache.client.ClientRegionShortcut;
import org.apache.geode.cache.client.Pool;
import org.apache.geode.cache.client.PoolFactory;
import org.apache.geode.cache.client.PoolManager;
import org.apache.geode.distributed.AbstractLauncher.ServiceState;
import org.apache.geode.distributed.AbstractLauncher.Status;
import org.apache.geode.distributed.LocatorLauncher;
import org.apache.geode.distributed.LocatorLauncher.Builder;
import org.apache.geode.distributed.LocatorLauncher.Command;
import org.apache.geode.distributed.LocatorLauncher.LocatorState;
import org.apache.geode.distributed.ServerLauncher;
import org.apache.geode.distributed.ServerLauncher.ServerState;
import org.apache.geode.distributed.internal.DistributionConfig;
import org.apache.geode.internal.AvailablePortHelper;
import org.apache.geode.internal.lang.ObjectUtils;
import org.apache.geode.internal.lang.StringUtils;
import org.apache.geode.internal.lang.SystemUtils;
import org.apache.geode.internal.process.ProcessType;
import org.apache.geode.internal.util.IOUtils;
import org.apache.geode.management.cli.Result;
import org.apache.geode.management.internal.cli.i18n.CliStrings;
import org.apache.geode.management.internal.cli.result.CommandResult;
import org.apache.geode.management.internal.cli.util.CommandStringBuilder;
import org.apache.geode.test.dunit.WaitCriterion;
import org.apache.geode.test.junit.categories.DistributedTest;
/**
* The LauncherLifecycleCommandsDUnitTest class is a test suite of integration tests testing the
* contract and functionality of the GemFire launcher lifecycle commands inside Gfsh.
*
* @see javax.management.MBeanServerConnection
* @see javax.management.remote.JMXConnector
* @see org.apache.geode.distributed.AbstractLauncher
* @see org.apache.geode.distributed.LocatorLauncher
* @see org.apache.geode.distributed.ServerLauncher
* @see org.apache.geode.internal.AvailablePortHelper
* @see org.apache.geode.management.internal.cli.shell.Gfsh
* @see org.apache.geode.management.internal.cli.commands.CliCommandTestBase
* @see org.apache.geode.management.internal.cli.commands.LauncherLifecycleCommands
* @see org.apache.geode.management.internal.cli.util.CommandStringBuilder
* @since GemFire 7.0
*/
@Category(DistributedTest.class)
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class LauncherLifecycleCommandsDUnitTest extends CliCommandTestBase {
protected static final DateFormat TIMESTAMP = new SimpleDateFormat("yyyyMMddHHmmssSSS");
private final Queue<Integer> processIds = new ConcurrentLinkedDeque<>();
protected static String getMemberId(final int jmxManagerPort, final String memberName)
throws Exception {
return getMemberId(InetAddress.getLocalHost().getHostName(), jmxManagerPort, memberName);
}
protected static String getMemberId(final String jmxManagerHost, final int jmxManagerPort,
final String memberName) throws Exception {
JMXConnector connector = null;
try {
connector = JMXConnectorFactory.connect(new JMXServiceURL(String.format(
"service:jmx:rmi://%1$s/jndi/rmi://%1$s:%2$d/jmxrmi", jmxManagerHost, jmxManagerPort)));
MBeanServerConnection connection = connector.getMBeanServerConnection();
ObjectName objectNamePattern = ObjectName.getInstance("GemFire:type=Member,*");
QueryExp query = Query.eq(Query.attr("Name"), Query.value(memberName));
Set<ObjectName> objectNames = connection.queryNames(objectNamePattern, query);
assertNotNull(objectNames);
assertFalse(objectNames.isEmpty());
assertEquals(1, objectNames.size());
// final ObjectName objectName = ObjectName.getInstance("GemFire:type=Member,Name=" +
// memberName);
ObjectName objectName = objectNames.iterator().next();
// System.err.printf("ObjectName for Member with Name (%1$s) is %2$s%n", memberName,
// objectName);
return ObjectUtils.toString(connection.getAttribute(objectName, "Id"));
} finally {
IOUtils.close(connector);
}
}
@Override
public final void postTearDown() throws Exception {
LauncherLifecycleCommands launcherLifecycleCommands = new LauncherLifecycleCommands();
Integer pid;
while ((pid = processIds.poll()) != null) {
if (launcherLifecycleCommands.isVmWithProcessIdRunning(pid)) {
try {
String killCommand = String.format("%1$s %2$d",
SystemUtils.isWindows() ? "taskkill /F /PID" : "kill -9", pid);
Runtime.getRuntime().exec(killCommand);
} catch (Throwable ignore) {
}
}
}
}
@SuppressWarnings("unused")
protected void assertStatus(final LocatorState expectedStatus, final LocatorState actualStatus) {
assertEquals(expectedStatus.getStatus(), actualStatus.getStatus());
assertEquals(expectedStatus.getTimestamp(), actualStatus.getTimestamp());
assertEquals(expectedStatus.getServiceLocation(), actualStatus.getServiceLocation());
assertTrue(ObjectUtils.equalsIgnoreNull(expectedStatus.getPid(), actualStatus.getPid()));
assertEquals(expectedStatus.getUptime(), actualStatus.getUptime());
assertEquals(expectedStatus.getWorkingDirectory(), actualStatus.getWorkingDirectory());
assertEquals(expectedStatus.getJvmArguments(), actualStatus.getJvmArguments());
assertEquals(expectedStatus.getClasspath(), actualStatus.getClasspath());
assertEquals(expectedStatus.getGemFireVersion(), actualStatus.getGemFireVersion());
assertEquals(expectedStatus.getJavaVersion(), actualStatus.getJavaVersion());
}
protected Integer readPid(final File workingDirectory) throws IOException {
assertTrue(String.format("The working directory (%1$s) must exist!", workingDirectory),
workingDirectory != null && workingDirectory.isDirectory());
File[] files = workingDirectory.listFiles(pathname -> (pathname != null && pathname.isFile()
&& pathname.getAbsolutePath().endsWith(".pid")));
assertNotNull(files);
assertTrue(files.length > 0);
File pidFile = files[0];
BufferedReader fileReader = null;
try {
fileReader = new BufferedReader(new FileReader(pidFile), 1024);
return Integer.parseInt(fileReader.readLine().trim());
} catch (Exception ignore) {
return null;
} finally {
IOUtils.close(fileReader);
}
}
protected String serviceStateStatusStringNormalized(final ServiceState serviceState) {
return serviceStateStatusStringNormalized(serviceState.toString());
}
protected String serviceStateStatusStringNormalized(final String serviceStateStatus) {
assertNotNull(serviceStateStatus);
assertTrue("serviceStateStatus is missing 'Uptime': " + serviceStateStatus,
serviceStateStatus.contains("Uptime"));
assertTrue("serviceStateStatus is missing 'JVM Arguments': " + serviceStateStatus,
serviceStateStatus.contains("JVM Arguments"));
return serviceStateStatus.substring(0, serviceStateStatus.indexOf("Uptime"))
.concat(serviceStateStatus.substring(serviceStateStatus.indexOf("JVM Arguments")));
}
protected Status stopLocator(final File workingDirectory) {
return stopLocator(IOUtils.tryGetCanonicalPathElseGetAbsolutePath(workingDirectory));
}
protected Status stopLocator(final String workingDirectory) {
return waitForGemFireProcessToStop(
new Builder().setCommand(Command.STOP).setWorkingDirectory(workingDirectory).build().stop(),
workingDirectory);
}
protected Status stopServer(final String workingDirectory) {
return waitForGemFireProcessToStop(
new ServerLauncher.Builder().setCommand(ServerLauncher.Command.STOP)
.setWorkingDirectory(workingDirectory).build().stop(),
workingDirectory);
}
protected String toString(final Result result) {
assert result != null : "The Result object from the command execution cannot be null!";
StringBuilder buffer = new StringBuilder(StringUtils.LINE_SEPARATOR);
while (result.hasNextLine()) {
buffer.append(result.nextLine());
buffer.append(StringUtils.LINE_SEPARATOR);
}
return buffer.toString();
}
protected Status waitForGemFireProcessToStop(final ServiceState serviceState,
final String workingDirectory) {
if (!Status.STOPPED.equals(serviceState.getStatus())) {
try {
final Integer pid = readPid(new File(workingDirectory));
if (pid != null) {
WaitCriterion waitCriteria = new WaitCriterion() {
private LauncherLifecycleCommands launcherLifecycleCommands =
new LauncherLifecycleCommands();
@Override
public boolean done() {
return !launcherLifecycleCommands.isVmWithProcessIdRunning(pid);
}
@Override
public String description() {
return String.format("Waiting for GemFire Process with PID (%1$d) to stop.", pid);
}
};
waitForCriterion(waitCriteria, TimeUnit.SECONDS.toMillis(15),
TimeUnit.SECONDS.toMillis(5), false);
if (!waitCriteria.done()) {
processIds.offer(pid);
}
}
} catch (IOException ignore) {
}
}
return serviceState.getStatus();
}
protected void writePid(final File pidFile, final int pid) throws IOException {
assertTrue("The PID file must actually exist!", pidFile != null && pidFile.isFile());
FileWriter writer = null;
try {
writer = new FileWriter(pidFile, false);
writer.write(String.valueOf(pid));
writer.write(System.getProperty("line.separator"));
writer.flush();
} finally {
IOUtils.close(writer);
}
}
@Test
public void test000StartLocatorCapturesOutputOnError() throws IOException {
final int locatorPort = AvailablePortHelper.getRandomAvailableTCPPort();
String pathname = (getClass().getSimpleName() + "_" + getTestMethodName());
File workingDirectory = temporaryFolder.newFolder(pathname);
assertTrue(workingDirectory.isDirectory() || workingDirectory.mkdir());
File pidFile = new File(workingDirectory, ProcessType.LOCATOR.getPidFileName());
assertTrue(pidFile.createNewFile());
writePid(pidFile, getPidOrOne());
pidFile.deleteOnExit();
assertTrue(pidFile.isFile());
CommandStringBuilder command = new CommandStringBuilder(CliStrings.START_LOCATOR);
command.addOption(CliStrings.START_LOCATOR__MEMBER_NAME, pathname);
command.addOption(CliStrings.START_LOCATOR__DIR, workingDirectory.getCanonicalPath());
command.addOption(CliStrings.START_LOCATOR__PORT, String.valueOf(locatorPort));
command.addOption(CliStrings.START_LOCATOR__ENABLE__SHARED__CONFIGURATION,
Boolean.FALSE.toString());
command.addOption(CliStrings.START_LOCATOR__J,
"-D" + DistributionConfig.GEMFIRE_PREFIX + "http-service-port=0");
command.addOption(CliStrings.START_LOCATOR__J, "-D" + DistributionConfig.GEMFIRE_PREFIX
+ "jmx-manager-port=" + AvailablePortHelper.getRandomAvailableTCPPort());
CommandResult result = executeCommand(command.toString());
assertNotNull(result);
assertEquals(Result.Status.ERROR, result.getStatus());
String resultString = toString(result);
assertTrue(resultString,
resultString.contains(
"Exception in thread \"main\" java.lang.RuntimeException: A PID file already exists and a Locator may be running in "
+ IOUtils.tryGetCanonicalFileElseGetAbsoluteFile(workingDirectory)));
assertTrue(resultString,
resultString.contains(
"Caused by: org.apache.geode.internal.process.FileAlreadyExistsException: Pid file already exists: "
+ IOUtils.tryGetCanonicalFileElseGetAbsoluteFile(pidFile)));
}
/*
* This method makes an effort to get the PID of the running process. If it is unable to determine
* accurately, it simply returns 1.
*/
private int getPidOrOne() {
int pid = 1;
String[] name = ManagementFactory.getRuntimeMXBean().getName().split("@");
if (name.length > 1) {
try {
pid = Integer.parseInt(name[0]);
} catch (NumberFormatException nex) {
// Ignored
}
}
return pid;
}
@Test
public void test001StartLocatorFailsFastOnMissingGemFirePropertiesFile() throws IOException {
String gemfirePropertiesPathname = "/path/to/missing/gemfire.properties";
CommandStringBuilder command = new CommandStringBuilder(CliStrings.START_LOCATOR);
String pathName = getClass().getSimpleName().concat("_").concat(getTestMethodName());
final File workingDirectory = temporaryFolder.newFolder(pathName);
command.addOption(CliStrings.START_LOCATOR__MEMBER_NAME, pathName);
command.addOption(CliStrings.START_LOCATOR__DIR, workingDirectory.getCanonicalPath());
command.addOption(CliStrings.START_LOCATOR__PORT, "0");
command.addOption(CliStrings.START_LOCATOR__PROPERTIES, gemfirePropertiesPathname);
command.addOption(CliStrings.START_LOCATOR__J,
"-D" + DistributionConfig.GEMFIRE_PREFIX + "http-service-port=0");
command.addOption(CliStrings.START_LOCATOR__J,
"-D" + DistributionConfig.GEMFIRE_PREFIX + "jmx-manager=false");
command.addOption(CliStrings.START_LOCATOR__J,
"-D" + DistributionConfig.GEMFIRE_PREFIX + "jmx-manager-port=0");
command.addOption(CliStrings.START_LOCATOR__J,
"-D" + DistributionConfig.GEMFIRE_PREFIX + "jmx-manager-start=false");
CommandResult result = executeCommand(command.toString());
assertNotNull(result);
assertEquals(Result.Status.ERROR, result.getStatus());
String resultString = toString(result);
assertTrue(resultString,
resultString
.contains(MessageFormat.format(CliStrings.GEODE_0_PROPERTIES_1_NOT_FOUND_MESSAGE,
StringUtils.EMPTY_STRING, gemfirePropertiesPathname)));
}
/**
* Test to verify GEODE-2138
*
* @throws IOException
*/
@Test
public void testVersionTitleForStartServerAndLocator() throws IOException {
final int locatorPort = AvailablePortHelper.getRandomAvailableTCPPort();
String pathname = (getClass().getSimpleName() + "_" + getTestMethodName());
String pathnameLoc = pathname + "_loc";
String pathnameSer = pathname + "_ser";
File workingDirectoryLoc = temporaryFolder.newFolder(pathnameLoc);
File workingDirectorySer = temporaryFolder.newFolder(pathnameSer);
assertTrue(workingDirectoryLoc.isDirectory() || workingDirectoryLoc.mkdir());
assertTrue(workingDirectorySer.isDirectory() || workingDirectorySer.mkdir());
try {
// verify the start locator output does not contain string "gemfire"
CommandStringBuilder locCommand = new CommandStringBuilder(CliStrings.START_LOCATOR);
locCommand.addOption(CliStrings.START_LOCATOR__MEMBER_NAME, pathnameLoc);
locCommand.addOption(CliStrings.START_LOCATOR__CONNECT, Boolean.FALSE.toString());
locCommand.addOption(CliStrings.START_LOCATOR__DIR, workingDirectoryLoc.getCanonicalPath());
locCommand.addOption(CliStrings.START_LOCATOR__PORT, String.valueOf(locatorPort));
CommandResult locResult = executeCommand(locCommand.toString());
assertNotNull(locResult);
assertEquals(Result.Status.OK, locResult.getStatus());
String locatorOutput = toString(locResult);
assertNotNull(locatorOutput);
assertTrue("Locator output was: " + locatorOutput, !locatorOutput.contains("Gemfire"));
// verify the start server output does not contain string "gemfire"
CommandStringBuilder serCommand = new CommandStringBuilder(CliStrings.START_SERVER);
serCommand.addOption(CliStrings.START_SERVER__NAME, pathnameSer);
serCommand.addOption(CliStrings.START_SERVER__DIR, workingDirectorySer.getCanonicalPath());
CommandResult serResult = executeCommand(serCommand.toString());
assertNotNull(serResult);
assertEquals(Result.Status.OK, serResult.getStatus());
String serverOutput = toString(serResult);
assertTrue("Server start output was: " + serverOutput, !serverOutput.contains("Gemfire"));
} finally {
stopLocator(workingDirectoryLoc);
stopServer(IOUtils.tryGetCanonicalPathElseGetAbsolutePath(workingDirectorySer));
}
}
@Test
public void test002StartLocatorFailsFastOnMissingGemFireSecurityPropertiesFile()
throws IOException {
String gemfireSecurityPropertiesPathname = "/path/to/missing/gemfire-security.properties";
String pathName = getClass().getSimpleName().concat("_").concat(getTestMethodName());
final File workingDirectory = temporaryFolder.newFolder(pathName);
CommandStringBuilder command = new CommandStringBuilder(CliStrings.START_LOCATOR);
command.addOption(CliStrings.START_LOCATOR__MEMBER_NAME, pathName);
command.addOption(CliStrings.START_LOCATOR__DIR, workingDirectory.getCanonicalPath());
command.addOption(CliStrings.START_LOCATOR__PORT, "0");
command.addOption(CliStrings.START_LOCATOR__SECURITY_PROPERTIES,
gemfireSecurityPropertiesPathname);
command.addOption(CliStrings.START_LOCATOR__J,
"-D" + DistributionConfig.GEMFIRE_PREFIX + "http-service-port=0");
command.addOption(CliStrings.START_LOCATOR__J,
"-D" + DistributionConfig.GEMFIRE_PREFIX + "jmx-manager=false");
command.addOption(CliStrings.START_LOCATOR__J,
"-D" + DistributionConfig.GEMFIRE_PREFIX + "jmx-manager-port=0");
command.addOption(CliStrings.START_LOCATOR__J,
"-D" + DistributionConfig.GEMFIRE_PREFIX + "jmx-manager-start=false");
CommandResult result = executeCommand(command.toString());
assertNotNull(result);
assertEquals(Result.Status.ERROR, result.getStatus());
String resultString = toString(result);
assertTrue(resultString,
resultString
.contains(MessageFormat.format(CliStrings.GEODE_0_PROPERTIES_1_NOT_FOUND_MESSAGE,
"Security ", gemfireSecurityPropertiesPathname)));
}
@Test
public void test003StartServerFailsFastOnMissingCacheXmlFile() throws IOException {
String cacheXmlPathname = "/path/to/missing/cache.xml";
CommandStringBuilder command = new CommandStringBuilder(CliStrings.START_SERVER);
String pathName = getClass().getSimpleName().concat("_").concat(getTestMethodName());
final File workingDirectory = temporaryFolder.newFolder(pathName);
command.addOption(CliStrings.START_SERVER__NAME, pathName);
command.addOption(CliStrings.START_SERVER__DIR, workingDirectory.getCanonicalPath());
command.addOption(CliStrings.START_SERVER__CACHE_XML_FILE, cacheXmlPathname);
CommandResult result = executeCommand(command.toString());
assertNotNull(result);
assertEquals(Result.Status.ERROR, result.getStatus());
String resultString = toString(result);
assertTrue(resultString, resultString
.contains(MessageFormat.format(CliStrings.CACHE_XML_NOT_FOUND_MESSAGE, cacheXmlPathname)));
}
@Test
public void test004StartServerFailsFastOnMissingGemFirePropertiesFile() throws IOException {
String gemfirePropertiesFile = "/path/to/missing/gemfire.properties";
CommandStringBuilder command = new CommandStringBuilder(CliStrings.START_SERVER);
String pathName = getClass().getSimpleName().concat("_").concat(getTestMethodName());
final File workingDirectory = temporaryFolder.newFolder(pathName);
command.addOption(CliStrings.START_SERVER__NAME, pathName);
command.addOption(CliStrings.START_SERVER__DIR, workingDirectory.getCanonicalPath());
command.addOption(CliStrings.START_SERVER__PROPERTIES, gemfirePropertiesFile);
CommandResult result = executeCommand(command.toString());
assertNotNull(result);
assertEquals(Result.Status.ERROR, result.getStatus());
String resultString = toString(result);
assertTrue(resultString,
resultString
.contains(MessageFormat.format(CliStrings.GEODE_0_PROPERTIES_1_NOT_FOUND_MESSAGE,
StringUtils.EMPTY_STRING, gemfirePropertiesFile)));
}
@Test
public void testStartServerFailsFastOnMissingPassword() throws IOException {
CommandStringBuilder command = new CommandStringBuilder(CliStrings.START_SERVER);
String pathName = getClass().getSimpleName().concat("_").concat(getTestMethodName());
final File workingDirectory = temporaryFolder.newFolder(pathName);
command.addOption(CliStrings.START_SERVER__NAME, pathName);
command.addOption(CliStrings.START_SERVER__DIR, workingDirectory.getCanonicalPath());
command.addOption(CliStrings.START_SERVER__USERNAME, "test");
CommandResult result = executeCommand(command.toString());
assertNotNull(result);
assertEquals(Result.Status.ERROR, result.getStatus());
String resultString = toString(result);
assertTrue(resultString, resultString.contains("password must be specified"));
}
@Test
public void test005StartServerFailsFastOnMissingGemFireSecurityPropertiesFile()
throws IOException {
String gemfireSecuritiesPropertiesFile = "/path/to/missing/gemfire-securities.properties";
CommandStringBuilder command = new CommandStringBuilder(CliStrings.START_SERVER);
String pathName = getClass().getSimpleName().concat("_").concat(getTestMethodName());
final File workingDirectory = temporaryFolder.newFolder(pathName);
command.addOption(CliStrings.START_SERVER__NAME, pathName);
command.addOption(CliStrings.START_SERVER__DIR, workingDirectory.getCanonicalPath());
command.addOption(CliStrings.START_SERVER__SECURITY_PROPERTIES,
gemfireSecuritiesPropertiesFile);
CommandResult result = executeCommand(command.toString());
assertNotNull(result);
assertEquals(Result.Status.ERROR, result.getStatus());
String resultString = toString(result);
assertTrue(resultString,
resultString
.contains(MessageFormat.format(CliStrings.GEODE_0_PROPERTIES_1_NOT_FOUND_MESSAGE,
"Security ", gemfireSecuritiesPropertiesFile)));
}
@Test
public void test006StartLocatorInRelativeDirectory() {
final int locatorPort = AvailablePortHelper.getRandomAvailableTCPPort();
String pathname = (getClass().getSimpleName() + "_" + getTestMethodName());
File workingDirectory = new File(pathname);
assertTrue(workingDirectory.isDirectory() || workingDirectory.mkdir());
try {
CommandStringBuilder command = new CommandStringBuilder(CliStrings.START_LOCATOR);
command.addOption(CliStrings.START_LOCATOR__MEMBER_NAME, pathname);
command.addOption(CliStrings.START_LOCATOR__CONNECT, Boolean.FALSE.toString());
command.addOption(CliStrings.START_LOCATOR__DIR, pathname);
command.addOption(CliStrings.START_LOCATOR__PORT, String.valueOf(locatorPort));
command.addOption(CliStrings.START_LOCATOR__ENABLE__SHARED__CONFIGURATION,
Boolean.FALSE.toString());
command.addOption(CliStrings.START_LOCATOR__J,
"-D" + DistributionConfig.GEMFIRE_PREFIX + "http-service-port=0");
command.addOption(CliStrings.START_LOCATOR__J, "-D" + DistributionConfig.GEMFIRE_PREFIX
+ "jmx-manager-port=" + AvailablePortHelper.getRandomAvailableTCPPort());
CommandResult result = executeCommand(command.toString());
assertNotNull(result);
assertEquals(Result.Status.OK, result.getStatus());
String locatorOutput = toString(result);
assertNotNull(locatorOutput);
assertTrue("Locator output was: " + locatorOutput, locatorOutput.contains(
"Locator in " + IOUtils.tryGetCanonicalFileElseGetAbsoluteFile(workingDirectory)));
} finally {
stopLocator(workingDirectory);
}
}
@Test
public void test007StatusLocatorUsingMemberNameIDWhenGfshIsNotConnected() {
CommandResult result =
executeCommand(CliStrings.STATUS_LOCATOR + " --name=" + getTestMethodName());
assertNotNull(result);
assertEquals(Result.Status.ERROR, result.getStatus());
assertEquals(
CliStrings.format(CliStrings.STATUS_SERVICE__GFSH_NOT_CONNECTED_ERROR_MESSAGE, "Locator"),
StringUtils.trim(toString(result)));
}
@Test
public void test008StatusLocatorUsingMemberName() throws IOException {
final int[] ports = AvailablePortHelper.getRandomAvailableTCPPorts(2);
final int jmxManagerPort = ports[0];
final int locatorPort = ports[1];
String pathname = (getClass().getSimpleName() + "_" + getTestMethodName());
File workingDirectory = temporaryFolder.newFolder(pathname);
assertTrue(workingDirectory.isDirectory() || workingDirectory.mkdir());
try {
CommandStringBuilder command = new CommandStringBuilder(CliStrings.START_LOCATOR);
command.addOption(CliStrings.START_LOCATOR__MEMBER_NAME, pathname);
command.addOption(CliStrings.START_LOCATOR__CONNECT, Boolean.FALSE.toString());
command.addOption(CliStrings.START_LOCATOR__DIR, workingDirectory.getCanonicalPath());
command.addOption(CliStrings.START_LOCATOR__PORT, String.valueOf(locatorPort));
command.addOption(CliStrings.START_LOCATOR__ENABLE__SHARED__CONFIGURATION,
Boolean.FALSE.toString());
command.addOption(CliStrings.START_LOCATOR__FORCE, Boolean.TRUE.toString());
command.addOption(CliStrings.START_LOCATOR__J,
"-D" + DistributionConfig.GEMFIRE_PREFIX + "http-service-port=0");
command.addOption(CliStrings.START_LOCATOR__J,
"-D" + DistributionConfig.GEMFIRE_PREFIX + "jmx-manager-port=" + jmxManagerPort);
CommandResult result = executeCommand(command.toString());
assertNotNull(result);
assertEquals(Result.Status.OK, result.getStatus());
LocatorLauncher locatorLauncher = new LocatorLauncher.Builder()
.setCommand(LocatorLauncher.Command.STATUS).setBindAddress(null).setPort(locatorPort)
.setWorkingDirectory(workingDirectory.getPath()).build();
assertNotNull(locatorLauncher);
LocatorState expectedLocatorState =
locatorLauncher.waitOnStatusResponse(60, 10, TimeUnit.SECONDS);
assertNotNull(expectedLocatorState);
assertEquals(Status.ONLINE, expectedLocatorState.getStatus());
result = executeCommand(
String.format("%1$s --locator=localhost[%2$d]", CliStrings.CONNECT, locatorPort));
assertNotNull(result);
assertEquals(Result.Status.OK, result.getStatus());
result = executeCommand(
String.format("%1$s --name=invalidLocatorMemberName", CliStrings.STATUS_LOCATOR));
assertNotNull(result);
assertEquals(Result.Status.ERROR, result.getStatus());
assertEquals(
CliStrings.format(CliStrings.STATUS_LOCATOR__NO_LOCATOR_FOUND_FOR_MEMBER_ERROR_MESSAGE,
"invalidLocatorMemberName"),
StringUtils.trim(toString(result)));
result =
executeCommand(String.format("%1$s --name=%2$s", CliStrings.STATUS_LOCATOR, pathname));
assertNotNull(result);
assertEquals(Result.Status.OK, result.getStatus());
assertTrue(serviceStateStatusStringNormalized(toString(result))
.contains(serviceStateStatusStringNormalized(expectedLocatorState)));
} finally {
stopLocator(workingDirectory);
}
}
@Test
public void test009StatusLocatorUsingMemberId() throws Exception {
final int[] ports = AvailablePortHelper.getRandomAvailableTCPPorts(2);
final int jmxManagerPort = ports[0];
final int locatorPort = ports[1];
String pathname = (getClass().getSimpleName() + "_" + getTestMethodName());
File workingDirectory = temporaryFolder.newFolder(pathname);
assertTrue(workingDirectory.isDirectory() || workingDirectory.mkdir());
try {
CommandStringBuilder command = new CommandStringBuilder(CliStrings.START_LOCATOR);
command.addOption(CliStrings.START_LOCATOR__MEMBER_NAME, pathname);
command.addOption(CliStrings.START_LOCATOR__CONNECT, Boolean.FALSE.toString());
command.addOption(CliStrings.START_LOCATOR__DIR, workingDirectory.getCanonicalPath());
command.addOption(CliStrings.START_LOCATOR__PORT, String.valueOf(locatorPort));
command.addOption(CliStrings.START_LOCATOR__ENABLE__SHARED__CONFIGURATION,
Boolean.FALSE.toString());
command.addOption(CliStrings.START_LOCATOR__FORCE, Boolean.TRUE.toString());
command.addOption(CliStrings.START_LOCATOR__J,
"-D" + DistributionConfig.GEMFIRE_PREFIX + "http-service-port=0");
command.addOption(CliStrings.START_LOCATOR__J,
"-D" + DistributionConfig.GEMFIRE_PREFIX + "jmx-manager-port=" + jmxManagerPort);
CommandResult result = executeCommand(command.toString());
assertNotNull(result);
assertEquals(Result.Status.OK, result.getStatus());
LocatorLauncher locatorLauncher = new LocatorLauncher.Builder()
.setCommand(LocatorLauncher.Command.STATUS).setBindAddress(null).setPort(locatorPort)
.setWorkingDirectory(workingDirectory.getPath()).build();
assertNotNull(locatorLauncher);
LocatorState expectedLocatorState =
locatorLauncher.waitOnStatusResponse(60, 10, TimeUnit.SECONDS);
assertNotNull(expectedLocatorState);
assertEquals(Status.ONLINE, expectedLocatorState.getStatus());
result = executeCommand(
String.format("%1$s --locator=localhost[%2$d]", CliStrings.CONNECT, locatorPort));
assertNotNull(result);
assertEquals(Result.Status.OK, result.getStatus());
result = executeCommand(String.format("%1$s --name=%2$s", CliStrings.STATUS_LOCATOR,
getMemberId(jmxManagerPort, pathname)));
assertNotNull(result);
assertEquals(Result.Status.OK, result.getStatus());
assertTrue(serviceStateStatusStringNormalized(toString(result))
.contains(serviceStateStatusStringNormalized(expectedLocatorState)));
} finally {
stopLocator(workingDirectory);
}
}
@Test
public void test010StopLocatorUsingMemberNameIDWhenGfshIsNotConnected() {
CommandResult result =
executeCommand(CliStrings.STOP_LOCATOR + " --name=" + getTestMethodName());
assertNotNull(result);
assertEquals(Result.Status.ERROR, result.getStatus());
assertEquals(
CliStrings.format(CliStrings.STOP_SERVICE__GFSH_NOT_CONNECTED_ERROR_MESSAGE, "Locator"),
StringUtils.trim(toString(result)));
}
@Test
public void test011StopLocatorUsingMemberName() throws IOException {
final int[] ports = AvailablePortHelper.getRandomAvailableTCPPorts(2);
final int jmxManagerPort = ports[0];
final int locatorPort = ports[1];
String pathname = (getClass().getSimpleName() + "_" + getTestMethodName());
File workingDirectory = temporaryFolder.newFolder(pathname);
try {
assertTrue(workingDirectory.isDirectory() || workingDirectory.mkdir());
CommandStringBuilder command = new CommandStringBuilder(CliStrings.START_LOCATOR);
command.addOption(CliStrings.START_LOCATOR__MEMBER_NAME, pathname);
command.addOption(CliStrings.START_LOCATOR__CONNECT, Boolean.FALSE.toString());
command.addOption(CliStrings.START_LOCATOR__DIR, workingDirectory.getCanonicalPath());
command.addOption(CliStrings.START_LOCATOR__PORT, String.valueOf(locatorPort));
command.addOption(CliStrings.START_LOCATOR__ENABLE__SHARED__CONFIGURATION,
Boolean.FALSE.toString());
command.addOption(CliStrings.START_LOCATOR__FORCE, Boolean.TRUE.toString());
command.addOption(CliStrings.START_LOCATOR__J,
"-D" + DistributionConfig.GEMFIRE_PREFIX + "http-service-port=0");
command.addOption(CliStrings.START_LOCATOR__J,
"-D" + DistributionConfig.GEMFIRE_PREFIX + "jmx-manager-port=" + jmxManagerPort);
CommandResult result = executeCommand(command.toString());
assertNotNull(result);
assertEquals(Result.Status.OK, result.getStatus());
final LocatorLauncher locatorLauncher =
new Builder().setCommand(Command.STOP).setBindAddress(null).setPort(locatorPort)
.setWorkingDirectory(workingDirectory.getPath()).build();
assertNotNull(locatorLauncher);
LocatorState locatorStatus = locatorLauncher.waitOnStatusResponse(60, 10, TimeUnit.SECONDS);
assertNotNull(locatorStatus);
assertEquals(Status.ONLINE, locatorStatus.getStatus());
result = executeCommand(
String.format("%1$s --locator=localhost[%2$d]", CliStrings.CONNECT, locatorPort));
assertNotNull(result);
assertEquals(Result.Status.OK, result.getStatus());
result = executeCommand(
String.format("%1$s --name=invalidLocatorMemberName", CliStrings.STOP_LOCATOR));
assertNotNull(result);
assertEquals(Result.Status.ERROR, result.getStatus());
assertEquals(
CliStrings.format(CliStrings.STOP_LOCATOR__NO_LOCATOR_FOUND_FOR_MEMBER_ERROR_MESSAGE,
"invalidLocatorMemberName"),
StringUtils.trim(toString(result)));
locatorStatus = locatorLauncher.status();
assertNotNull(locatorStatus);
assertEquals(Status.ONLINE, locatorStatus.getStatus());
result = executeCommand(String.format("%1$s --name=%2$s", CliStrings.STOP_LOCATOR, pathname));
assertNotNull(result);
assertEquals(Result.Status.OK, result.getStatus());
// TODO figure out what output to assert and validate on now that 'stop locator' uses Gfsh's
// logger
// and standard err/out...
// assertIndexDetailsEquals(CliStrings.format(CliStrings.STOP_LOCATOR__SHUTDOWN_MEMBER_MESSAGE,
// pathname),
// StringUtils.trim(toString(result)));
WaitCriterion waitCriteria = new WaitCriterion() {
@Override
public boolean done() {
final LocatorState locatorStatus = locatorLauncher.status();
return (locatorStatus != null && Status.NOT_RESPONDING.equals(locatorStatus.getStatus()));
}
@Override
public String description() {
return "wait for the Locator to stop; the Locator will no longer respond after it stops";
}
};
waitForCriterion(waitCriteria, 15 * 1000, 5000, true);
locatorStatus = locatorLauncher.status();
assertNotNull(locatorStatus);
assertEquals(Status.NOT_RESPONDING, locatorStatus.getStatus());
} finally {
}
}
// @see Trac Bug # 46760
@Test
public void test012StopLocatorUsingMemberId() throws Exception {
final int[] ports = AvailablePortHelper.getRandomAvailableTCPPorts(2);
final int jmxManagerPort = ports[0];
final int locatorPort = ports[1];
String pathname = (getClass().getSimpleName() + "_" + getTestMethodName());
File workingDirectory = temporaryFolder.newFolder(pathname);
try {
assertTrue(workingDirectory.isDirectory() || workingDirectory.mkdir());
CommandStringBuilder command = new CommandStringBuilder(CliStrings.START_LOCATOR);
command.addOption(CliStrings.START_LOCATOR__MEMBER_NAME, pathname);
command.addOption(CliStrings.START_LOCATOR__CONNECT, Boolean.FALSE.toString());
command.addOption(CliStrings.START_LOCATOR__DIR, workingDirectory.getCanonicalPath());
command.addOption(CliStrings.START_LOCATOR__PORT, String.valueOf(locatorPort));
command.addOption(CliStrings.START_LOCATOR__ENABLE__SHARED__CONFIGURATION,
Boolean.FALSE.toString());
command.addOption(CliStrings.START_LOCATOR__FORCE, Boolean.TRUE.toString());
command.addOption(CliStrings.START_LOCATOR__J,
"-D" + DistributionConfig.GEMFIRE_PREFIX + "http-service-port=0");
command.addOption(CliStrings.START_LOCATOR__J,
"-D" + DistributionConfig.GEMFIRE_PREFIX + "jmx-manager-port=" + jmxManagerPort);
CommandResult result = executeCommand(command.toString());
assertNotNull(result);
assertEquals(Result.Status.OK, result.getStatus());
final LocatorLauncher locatorLauncher =
new Builder().setCommand(Command.STOP).setBindAddress(null).setPort(locatorPort)
.setWorkingDirectory(workingDirectory.getPath()).build();
assertNotNull(locatorLauncher);
LocatorState locatorState = locatorLauncher.waitOnStatusResponse(60, 10, TimeUnit.SECONDS);
assertNotNull(locatorState);
assertEquals(Status.ONLINE, locatorState.getStatus());
result = executeCommand(
String.format("%1$s --locator=localhost[%2$d]", CliStrings.CONNECT, locatorPort));
assertNotNull(result);
assertEquals(Result.Status.OK, result.getStatus());
String memberId = getMemberId(jmxManagerPort, pathname);
result = executeCommand(String.format("%1$s --name=%2$s", CliStrings.STOP_LOCATOR, memberId));
assertNotNull(result);
assertEquals(Result.Status.OK, result.getStatus());
// TODO figure out what output to assert and validate on now that 'stop locator' uses Gfsh's
// logger
// and standard err/out...
// assertIndexDetailsEquals(CliStrings.format(CliStrings.STOP_LOCATOR__SHUTDOWN_MEMBER_MESSAGE,
// memberId),
// StringUtils.trim(toString(result)));
WaitCriterion waitCriteria = new WaitCriterion() {
@Override
public boolean done() {
LocatorState locatorState = locatorLauncher.status();
return (locatorState != null && Status.NOT_RESPONDING.equals(locatorState.getStatus()));
}
@Override
public String description() {
return "wait for the Locator to stop; the Locator will no longer respond after it stops";
}
};
waitForCriterion(waitCriteria, 15 * 1000, 5000, true);
locatorState = locatorLauncher.status();
assertNotNull(locatorState);
assertEquals(Status.NOT_RESPONDING, locatorState.getStatus());
} finally {
}
}
@Test
public void test014GemFireServerJvmProcessTerminatesOnOutOfMemoryError() throws Exception {
int ports[] = AvailablePortHelper.getRandomAvailableTCPPorts(2);
final int serverPort = ports[0];
final int locatorPort = ports[1];
String pathname = getClass().getSimpleName().concat("_").concat(getTestMethodName());
File workingDirectory = temporaryFolder.newFolder(pathname);
assertTrue(workingDirectory.isDirectory() || workingDirectory.mkdir());
CommandStringBuilder command = new CommandStringBuilder(CliStrings.START_SERVER);
command.addOption(CliStrings.START_SERVER__NAME,
pathname + TIMESTAMP.format(Calendar.getInstance().getTime()));
command.addOption(CliStrings.START_SERVER__SERVER_PORT, String.valueOf(serverPort));
command.addOption(CliStrings.START_SERVER__USE_CLUSTER_CONFIGURATION, Boolean.FALSE.toString());
command.addOption(CliStrings.START_SERVER__MAXHEAP, "10M");
command.addOption(CliStrings.START_SERVER__LOG_LEVEL, "config");
command.addOption(CliStrings.START_SERVER__DIR, workingDirectory.getCanonicalPath());
command.addOption(CliStrings.START_SERVER__CACHE_XML_FILE,
IOUtils.tryGetCanonicalPathElseGetAbsolutePath(writeAndGetCacheXmlFile(workingDirectory)));
command.addOption(CliStrings.START_SERVER__INCLUDE_SYSTEM_CLASSPATH);
command.addOption(CliStrings.START_SERVER__J, "-D" + DistributionConfig.GEMFIRE_PREFIX + ""
+ START_LOCATOR + "=localhost[" + locatorPort + "]");
CommandResult result = executeCommand(command.toString());
System.out.println("result=" + result);
assertNotNull(result);
assertEquals(Result.Status.OK, result.getStatus());
ServerLauncher serverLauncher =
new ServerLauncher.Builder().setCommand(ServerLauncher.Command.STATUS)
.setWorkingDirectory(IOUtils.tryGetCanonicalPathElseGetAbsolutePath(workingDirectory))
.build();
assertNotNull(serverLauncher);
ServerState serverState = serverLauncher.status();
assertNotNull(serverState);
assertEquals(Status.ONLINE, serverState.getStatus());
// Verify our GemFire Server JVM process is running!
assertTrue(new LauncherLifecycleCommands().isVmWithProcessIdRunning(serverState.getPid()));
ClientCache clientCache = setupClientCache(pathname + String.valueOf(serverPort), serverPort);
assertNotNull(clientCache);
try {
Region<Long, String> exampleRegion = clientCache.getRegion("/Example");
// run the GemFire Server "out-of-town" with an OutOfMemoryError!
for (long index = 0; index < Long.MAX_VALUE; index++) {
exampleRegion.put(index, String.valueOf(index));
}
} catch (Exception ignore) {
System.err.printf("%1$s: %2$s%n", ignore.getClass().getName(), ignore.getMessage());
} finally {
clientCache.close();
final int serverPid = serverState.getPid();
WaitCriterion waitCriteria = new WaitCriterion() {
private LauncherLifecycleCommands launcherLifecycleCommands =
new LauncherLifecycleCommands();
@Override
public boolean done() {
return !launcherLifecycleCommands.isVmWithProcessIdRunning(serverPid);
}
@Override
public String description() {
return "Wait for the GemFire Server JVM process that ran out-of-memory to exit.";
}
};
waitForCriterion(waitCriteria, TimeUnit.SECONDS.toMillis(30), TimeUnit.SECONDS.toMillis(10),
true);
// Verify our GemFire Server JVM process is was terminated!
assertFalse(new LauncherLifecycleCommands().isVmWithProcessIdRunning(serverState.getPid()));
serverState = serverLauncher.status();
assertNotNull(serverState);
assertEquals(Status.NOT_RESPONDING, serverState.getStatus());
}
}
private File writeAndGetCacheXmlFile(final File workingDirectory) throws IOException {
File cacheXml = new File(workingDirectory, "cache.xml");
StringBuilder buffer = new StringBuilder("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
buffer.append(StringUtils.LINE_SEPARATOR);
buffer.append(
"<!DOCTYPE cache PUBLIC \"-//GemStone Systems, Inc.//GemFire Declarative Caching 7.0//EN\"");
buffer.append(StringUtils.LINE_SEPARATOR);
buffer.append(" \"http://www.gemstone.com/dtd/cache7_0.dtd\">");
buffer.append(StringUtils.LINE_SEPARATOR);
buffer.append("<cache>");
buffer.append(StringUtils.LINE_SEPARATOR);
buffer.append(" <region name=\"Example\" refid=\"REPLICATE\"/>");
buffer.append(StringUtils.LINE_SEPARATOR);
buffer.append("</cache>");
BufferedWriter fileWriter = null;
try {
fileWriter = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(cacheXml, false),
Charset.forName("UTF-8").newEncoder()));
fileWriter.write(buffer.toString());
fileWriter.flush();
} finally {
IOUtils.close(fileWriter);
}
return cacheXml;
}
private ClientCache setupClientCache(final String durableClientId, final int serverPort) {
ClientCache clientCache =
new ClientCacheFactory().set(DURABLE_CLIENT_ID, durableClientId).create();
PoolFactory poolFactory = PoolManager.createFactory();
poolFactory.setMaxConnections(10);
poolFactory.setMinConnections(1);
poolFactory.setReadTimeout(5000);
poolFactory.addServer("localhost", serverPort);
Pool pool = poolFactory.create("serverConnectionPool");
assertNotNull("The 'serverConnectionPool' was not properly configured and initialized!", pool);
ClientRegionFactory<Long, String> regionFactory =
clientCache.createClientRegionFactory(ClientRegionShortcut.PROXY);
regionFactory.setPoolName(pool.getName());
regionFactory.setKeyConstraint(Long.class);
regionFactory.setValueConstraint(String.class);
Region<Long, String> exampleProxy = regionFactory.create("Example");
assertNotNull("The 'Example' Client Region was not properly configured and initialized",
exampleProxy);
return clientCache;
}
}