/* * 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.junit.Assert.*; import java.io.File; import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Properties; import java.util.Set; import java.util.Stack; import org.junit.After; import org.junit.Before; import org.junit.Test; import org.junit.experimental.categories.Category; import org.apache.geode.GemFireException; import org.apache.geode.cache.server.CacheServer; import org.apache.geode.distributed.ServerLauncher; import org.apache.geode.distributed.internal.DistributionConfig; import org.apache.geode.internal.DistributionLocator; import org.apache.geode.internal.lang.StringUtils; import org.apache.geode.internal.lang.SystemUtils; import org.apache.geode.internal.util.IOUtils; import org.apache.geode.management.internal.cli.i18n.CliStrings; import org.apache.geode.test.junit.categories.UnitTest; /** * The LauncherLifecycleCommandsJUnitTest class is a test suite of test cases testing the contract * and functionality of the lifecycle launcher GemFire shell (Gfsh) commands. * * @see org.apache.geode.management.internal.cli.commands.LauncherLifecycleCommands * @see org.junit.Assert * @see org.junit.Test * @since GemFire 7.0 */ @Category(UnitTest.class) @SuppressWarnings("unused") public class LauncherLifecycleCommandsJUnitTest { private LauncherLifecycleCommands launcherCommands; @Before public void setup() { launcherCommands = new LauncherLifecycleCommands(); } @After public void tearDown() { launcherCommands = null; } @Test public void testAddGemFirePropertyFileToCommandLine() { final List<String> commandLine = new ArrayList<>(); assertTrue(commandLine.isEmpty()); getLauncherLifecycleCommands().addGemFirePropertyFile(commandLine, null); assertTrue(commandLine.isEmpty()); getLauncherLifecycleCommands().addGemFirePropertyFile(commandLine, StringUtils.EMPTY_STRING); assertTrue(commandLine.isEmpty()); getLauncherLifecycleCommands().addGemFirePropertyFile(commandLine, " "); assertTrue(commandLine.isEmpty()); getLauncherLifecycleCommands().addGemFirePropertyFile(commandLine, "/path/to/gemfire.properties"); assertFalse(commandLine.isEmpty()); assertTrue(commandLine.contains("-DgemfirePropertyFile=/path/to/gemfire.properties")); } @Test public void testAddGemFireSystemPropertiesToCommandLine() { final List<String> commandLine = new ArrayList<>(); assertTrue(commandLine.isEmpty()); getLauncherLifecycleCommands().addGemFireSystemProperties(commandLine, new Properties()); assertTrue(commandLine.isEmpty()); final Properties gemfireProperties = new Properties(); gemfireProperties.setProperty(LOCATORS, "localhost[11235]"); gemfireProperties.setProperty(LOG_LEVEL, "config"); gemfireProperties.setProperty(LOG_FILE, StringUtils.EMPTY_STRING); gemfireProperties.setProperty(MCAST_PORT, "0"); gemfireProperties.setProperty(NAME, "machine"); getLauncherLifecycleCommands().addGemFireSystemProperties(commandLine, gemfireProperties); assertFalse(commandLine.isEmpty()); assertEquals(4, commandLine.size()); for (final String propertyName : gemfireProperties.stringPropertyNames()) { final String propertyValue = gemfireProperties.getProperty(propertyName); if (StringUtils.isBlank(propertyValue)) { for (final String systemProperty : commandLine) { assertFalse(systemProperty.startsWith( "-D" + DistributionConfig.GEMFIRE_PREFIX + "".concat(propertyName).concat("="))); } } else { assertTrue(commandLine.contains("-D" + DistributionConfig.GEMFIRE_PREFIX + "".concat(propertyName).concat("=").concat(propertyValue))); } } } @Test public void testAddGemFireSystemPropertiesToCommandLineWithRestAPI() { final List<String> commandLine = new ArrayList<>(); assertTrue(commandLine.isEmpty()); getLauncherLifecycleCommands().addGemFireSystemProperties(commandLine, new Properties()); assertTrue(commandLine.isEmpty()); final Properties gemfireProperties = new Properties(); gemfireProperties.setProperty(LOCATORS, "localhost[11235]"); gemfireProperties.setProperty(LOG_LEVEL, "config"); gemfireProperties.setProperty(LOG_FILE, StringUtils.EMPTY_STRING); gemfireProperties.setProperty(MCAST_PORT, "0"); gemfireProperties.setProperty(NAME, "machine"); gemfireProperties.setProperty(START_DEV_REST_API, "true"); gemfireProperties.setProperty(HTTP_SERVICE_PORT, "8080"); gemfireProperties.setProperty(HTTP_SERVICE_BIND_ADDRESS, "localhost"); getLauncherLifecycleCommands().addGemFireSystemProperties(commandLine, gemfireProperties); assertFalse(commandLine.isEmpty()); assertEquals(7, commandLine.size()); for (final String propertyName : gemfireProperties.stringPropertyNames()) { final String propertyValue = gemfireProperties.getProperty(propertyName); if (StringUtils.isBlank(propertyValue)) { for (final String systemProperty : commandLine) { assertFalse(systemProperty.startsWith( "-D" + DistributionConfig.GEMFIRE_PREFIX + "".concat(propertyName).concat("="))); } } else { assertTrue(commandLine.contains("-D" + DistributionConfig.GEMFIRE_PREFIX + "".concat(propertyName).concat("=").concat(propertyValue))); } } } @Test public void testAddInitialHeapToCommandLine() { final List<String> commandLine = new ArrayList<>(); assertTrue(commandLine.isEmpty()); getLauncherLifecycleCommands().addInitialHeap(commandLine, null); assertTrue(commandLine.isEmpty()); getLauncherLifecycleCommands().addInitialHeap(commandLine, StringUtils.EMPTY_STRING); assertTrue(commandLine.isEmpty()); getLauncherLifecycleCommands().addInitialHeap(commandLine, " "); assertTrue(commandLine.isEmpty()); getLauncherLifecycleCommands().addInitialHeap(commandLine, "512M"); assertFalse(commandLine.isEmpty()); assertEquals("-Xms512M", commandLine.get(0)); } @Test public void testAddJvmArgumentsAndOptionsToCommandLine() { final List<String> commandLine = new ArrayList<>(); assertTrue(commandLine.isEmpty()); getLauncherLifecycleCommands().addJvmArgumentsAndOptions(commandLine, null); assertTrue(commandLine.isEmpty()); getLauncherLifecycleCommands().addJvmArgumentsAndOptions(commandLine, new String[] {}); assertTrue(commandLine.isEmpty()); getLauncherLifecycleCommands().addJvmArgumentsAndOptions(commandLine, new String[] {"-DmyProp=myVal", "-d64", "-server", "-Xprof"}); assertFalse(commandLine.isEmpty()); assertEquals(4, commandLine.size()); assertEquals("-DmyProp=myVal", commandLine.get(0)); assertEquals("-d64", commandLine.get(1)); assertEquals("-server", commandLine.get(2)); assertEquals("-Xprof", commandLine.get(3)); } // Fix for Bug #47192 - "Making GemFire (JVM) to exit in case of OutOfMemory" @Test public void testAddJvmOptionsForOutOfMemoryErrors() { final List<String> jvmOptions = new ArrayList<>(1); getLauncherLifecycleCommands().addJvmOptionsForOutOfMemoryErrors(jvmOptions); if (SystemUtils.isHotSpotVM()) { if (SystemUtils.isWindows()) { assertTrue(jvmOptions.contains("-XX:OnOutOfMemoryError=taskkill /F /PID %p")); } else { assertTrue(jvmOptions.contains("-XX:OnOutOfMemoryError=kill -KILL %p")); } } else if (SystemUtils.isJ9VM()) { assertEquals(1, jvmOptions.size()); assertTrue(jvmOptions.contains("-Xcheck:memory")); } else if (SystemUtils.isJRockitVM()) { assertEquals(1, jvmOptions.size()); assertTrue(jvmOptions.contains("-XXexitOnOutOfMemory")); } else { assertTrue(jvmOptions.isEmpty()); } } @Test public void testAddMaxHeapToCommandLine() { final List<String> commandLine = new ArrayList<>(); assertTrue(commandLine.isEmpty()); getLauncherLifecycleCommands().addMaxHeap(commandLine, null); assertTrue(commandLine.isEmpty()); getLauncherLifecycleCommands().addMaxHeap(commandLine, StringUtils.EMPTY_STRING); assertTrue(commandLine.isEmpty()); getLauncherLifecycleCommands().addMaxHeap(commandLine, " "); assertTrue(commandLine.isEmpty()); getLauncherLifecycleCommands().addMaxHeap(commandLine, "1024M"); assertFalse(commandLine.isEmpty()); assertEquals(3, commandLine.size()); assertEquals("-Xmx1024M", commandLine.get(0)); assertEquals("-XX:+UseConcMarkSweepGC", commandLine.get(1)); assertEquals("-XX:CMSInitiatingOccupancyFraction=" + LauncherLifecycleCommands.CMS_INITIAL_OCCUPANCY_FRACTION, commandLine.get(2)); } @Test(expected = AssertionError.class) public void testReadPidWithNull() { try { getLauncherLifecycleCommands().readPid(null); } catch (AssertionError expected) { assertEquals("The file from which to read the process ID (pid) cannot be null!", expected.getMessage()); throw expected; } } @Test @SuppressWarnings("deprecation") public void testGetClasspath() { assertEquals(System.getProperty("java.class.path"), getLauncherLifecycleCommands().getClasspath(null)); } @Test @SuppressWarnings("deprecation") public void testGetClasspathWithUserDefinedClasspath() { assertEquals( System.getProperty("java.class.path") + File.pathSeparator + "/path/to/user/classes", getLauncherLifecycleCommands().getClasspath("/path/to/user/classes")); } @Test public void testGetSystemClasspath() { assertEquals(System.getProperty("java.class.path"), getLauncherLifecycleCommands().getSystemClasspath()); } @Test public void testLocatorClasspathOrder() { String userClasspath = "/path/to/user/lib/app.jar:/path/to/user/classes"; String expectedClasspath = launcherCommands.getGemFireJarPath().concat(File.pathSeparator) .concat(userClasspath).concat(File.pathSeparator) .concat(System.getProperty("java.class.path")).concat(File.pathSeparator) .concat(LauncherLifecycleCommands.CORE_DEPENDENCIES_JAR_PATHNAME); String actualClasspath = launcherCommands.getLocatorClasspath(true, userClasspath); assertEquals(expectedClasspath, actualClasspath); } @Test public void testServerClasspathOrder() { String userClasspath = "/path/to/user/lib/app.jar:/path/to/user/classes"; String expectedClasspath = launcherCommands.getGemFireJarPath().concat(File.pathSeparator) .concat(userClasspath).concat(File.pathSeparator) .concat(LauncherLifecycleCommands.CORE_DEPENDENCIES_JAR_PATHNAME); String actualClasspath = launcherCommands.getServerClasspath(false, userClasspath); assertEquals(expectedClasspath, actualClasspath); } @Test public void testToClasspath() { final boolean EXCLUDE_SYSTEM_CLASSPATH = false; final boolean INCLUDE_SYSTEM_CLASSPATH = true; String[] jarFilePathnames = {"/path/to/user/libs/A.jar", "/path/to/user/libs/B.jar", "/path/to/user/libs/C.jar"}; String[] userClasspaths = {"/path/to/classes:/path/to/libs/1.jar:/path/to/libs/2.jar", "/path/to/ext/libs/1.jar:/path/to/ext/classes:/path/to/ext/lib/10.jar"}; String expectedClasspath = LauncherLifecycleCommands.GEODE_JAR_PATHNAME .concat(File.pathSeparator).concat(toClasspath(userClasspaths)).concat(File.pathSeparator) .concat(toClasspath(jarFilePathnames)); assertEquals(expectedClasspath, getLauncherLifecycleCommands() .toClasspath(EXCLUDE_SYSTEM_CLASSPATH, jarFilePathnames, userClasspaths)); expectedClasspath = LauncherLifecycleCommands.GEODE_JAR_PATHNAME.concat(File.pathSeparator) .concat(toClasspath(userClasspaths)).concat(File.pathSeparator) .concat(System.getProperty("java.class.path")).concat(File.pathSeparator) .concat(toClasspath(jarFilePathnames)); assertEquals(expectedClasspath, getLauncherLifecycleCommands() .toClasspath(INCLUDE_SYSTEM_CLASSPATH, jarFilePathnames, userClasspaths)); expectedClasspath = LauncherLifecycleCommands.GEODE_JAR_PATHNAME.concat(File.pathSeparator) .concat(System.getProperty("java.class.path")); assertEquals(expectedClasspath, getLauncherLifecycleCommands() .toClasspath(INCLUDE_SYSTEM_CLASSPATH, null, (String[]) null)); assertEquals(LauncherLifecycleCommands.GEODE_JAR_PATHNAME, getLauncherLifecycleCommands() .toClasspath(EXCLUDE_SYSTEM_CLASSPATH, null, (String[]) null)); assertEquals(LauncherLifecycleCommands.GEODE_JAR_PATHNAME, getLauncherLifecycleCommands().toClasspath(EXCLUDE_SYSTEM_CLASSPATH, new String[0], "")); } @Test public void testToClassPathOrder() { String userClasspathOne = "/path/to/user/lib/a.jar:/path/to/user/classes"; String userClasspathTwo = "/path/to/user/lib/x.jar:/path/to/user/lib/y.jar:/path/to/user/lib/z.jar"; String expectedClasspath = launcherCommands.getGemFireJarPath().concat(File.pathSeparator) .concat(userClasspathOne).concat(File.pathSeparator).concat(userClasspathTwo) .concat(File.pathSeparator).concat(System.getProperty("java.class.path")) .concat(File.pathSeparator).concat(LauncherLifecycleCommands.CORE_DEPENDENCIES_JAR_PATHNAME) .concat(File.pathSeparator) .concat(LauncherLifecycleCommands.CORE_DEPENDENCIES_JAR_PATHNAME); String actualClasspath = launcherCommands.toClasspath(true, new String[] {LauncherLifecycleCommands.CORE_DEPENDENCIES_JAR_PATHNAME, LauncherLifecycleCommands.CORE_DEPENDENCIES_JAR_PATHNAME}, userClasspathOne, userClasspathTwo); assertEquals(expectedClasspath, actualClasspath); } @Test public void testGetJavaPathname() { assertEquals( IOUtils.appendToPath(System.getProperty("java.home"), "bin", "java" + LauncherLifecycleCommands.getExecutableSuffix()), getLauncherLifecycleCommands().getJdkToolPathname( "java" + LauncherLifecycleCommands.getExecutableSuffix(), new GemFireException() {})); } @Test(expected = NullPointerException.class) public void testGetJdkToolPathnameWithNullPathnames() { try { getLauncherLifecycleCommands().getJdkToolPathname((Stack<String>) null, new GemFireException() {}); } catch (NullPointerException expected) { assertEquals("The JDK tool executable pathnames cannot be null!", expected.getMessage()); throw expected; } } @Test(expected = NullPointerException.class) public void testGetJdkToolPathnameWithNullGemFireException() { try { getLauncherLifecycleCommands().getJdkToolPathname(new Stack<String>(), null); } catch (NullPointerException expected) { assertEquals("The GemFireException cannot be null!", expected.getMessage()); throw expected; } } @Test public void testGetJdkToolPathnameForNonExistingTool() { try { final GemFireException expected = new GemFireException() { @Override public String getMessage() { return "expected"; } }; getLauncherLifecycleCommands().getJdkToolPathname("nonExistingTool.exe", expected); } catch (GemFireException expected) { assertEquals("expected", expected.getMessage()); } } @Test public void testGetLocatorId() { assertEquals("machine[11235]", getLauncherLifecycleCommands().getLocatorId("machine", 11235)); assertEquals("machine.domain.org[11235]", getLauncherLifecycleCommands().getLocatorId("machine.domain.org", 11235)); assertEquals("machine[" + DistributionLocator.DEFAULT_LOCATOR_PORT + "]", getLauncherLifecycleCommands().getLocatorId("machine", null)); } @Test public void testGetServerId() { assertEquals("machine[12480]", getLauncherLifecycleCommands().getServerId("machine", 12480)); assertEquals("machine.domain.org[12480]", getLauncherLifecycleCommands().getServerId("machine.domain.org", 12480)); assertEquals("machine[" + CacheServer.DEFAULT_PORT + "]", getLauncherLifecycleCommands().getServerId("machine", null)); } @Test public void testCreateJmxServerUrlWithMemberName() { assertEquals("service:jmx:rmi://localhost:8192/jndi/rmi://localhost:8192/jmxrmi", getLauncherLifecycleCommands().getJmxServiceUrlAsString("localhost[8192]")); } @Test(expected = IllegalArgumentException.class) public void testCreateJmxServiceUrlWithInvalidMemberName() { try { System.err.println(getLauncherLifecycleCommands().getJmxServiceUrlAsString("memberOne[]")); } catch (IllegalArgumentException expected) { assertEquals(CliStrings.START_JCONSOLE__CONNECT_BY_MEMBER_NAME_ID_ERROR_MESSAGE, expected.getMessage()); throw expected; } } @Test public void testCreateServerCommandLine() throws Exception { ServerLauncher serverLauncher = new ServerLauncher.Builder() .setCommand(ServerLauncher.Command.START).setDisableDefaultServer(true) .setMemberName("testCreateServerCommandLine").setRebalance(true) // .setServerBindAddress("localhost") .setServerPort(41214).setCriticalHeapPercentage(95.5f).setEvictionHeapPercentage(85.0f) .setSocketBufferSize(1024 * 1024).setMessageTimeToLive(93).build(); String[] commandLineElements = launcherCommands.createStartServerCommandLine(serverLauncher, null, null, new Properties(), null, false, new String[0], false, null, null); assertNotNull(commandLineElements); assertTrue(commandLineElements.length > 0); Set<String> expectedCommandLineElements = new HashSet<>(6); expectedCommandLineElements.add(serverLauncher.getCommand().getName()); expectedCommandLineElements.add("--disable-default-server"); expectedCommandLineElements.add(serverLauncher.getMemberName().toLowerCase()); expectedCommandLineElements.add("--rebalance"); // expectedCommandLineElements.add(String.format("--server-bind-address=%1$s", // serverLauncher.getServerBindAddress().getHostName())); expectedCommandLineElements .add(String.format("--server-port=%1$d", serverLauncher.getServerPort())); expectedCommandLineElements.add(String.format("--critical-heap-percentage=%1$s", serverLauncher.getCriticalHeapPercentage())); expectedCommandLineElements.add(String.format("--eviction-heap-percentage=%1$s", serverLauncher.getEvictionHeapPercentage())); expectedCommandLineElements .add(String.format("--socket-buffer-size=%1$d", serverLauncher.getSocketBufferSize())); expectedCommandLineElements .add(String.format("--message-time-to-live=%1$d", serverLauncher.getMessageTimeToLive())); for (String commandLineElement : commandLineElements) { expectedCommandLineElements.remove(commandLineElement.toLowerCase()); } assertTrue(String.format("Expected ([]); but was (%1$s)", expectedCommandLineElements), expectedCommandLineElements.isEmpty()); } @Test public void testCreateServerCommandLineWithRestAPI() throws Exception { ServerLauncher serverLauncher = new ServerLauncher.Builder() .setCommand(ServerLauncher.Command.START).setDisableDefaultServer(true) .setMemberName("testCreateServerCommandLine").setRebalance(true) // .setServerBindAddress("localhost") .setServerPort(41214).setCriticalHeapPercentage(95.5f).setEvictionHeapPercentage(85.0f) .build(); Properties gemfireProperties = new Properties(); gemfireProperties.setProperty(START_DEV_REST_API, "true"); gemfireProperties.setProperty(HTTP_SERVICE_PORT, "8080"); gemfireProperties.setProperty(HTTP_SERVICE_BIND_ADDRESS, "localhost"); String[] commandLineElements = launcherCommands.createStartServerCommandLine(serverLauncher, null, null, gemfireProperties, null, false, new String[0], false, null, null); assertNotNull(commandLineElements); assertTrue(commandLineElements.length > 0); Set<String> expectedCommandLineElements = new HashSet<>(6); expectedCommandLineElements.add(serverLauncher.getCommand().getName()); expectedCommandLineElements.add("--disable-default-server"); expectedCommandLineElements.add(serverLauncher.getMemberName().toLowerCase()); expectedCommandLineElements.add("--rebalance"); // expectedCommandLineElements.add(String.format("--server-bind-address=%1$s", // serverLauncher.getServerBindAddress().getHostName())); expectedCommandLineElements .add(String.format("--server-port=%1$d", serverLauncher.getServerPort())); expectedCommandLineElements.add(String.format("--critical-heap-percentage=%1$s", serverLauncher.getCriticalHeapPercentage())); expectedCommandLineElements.add(String.format("--eviction-heap-percentage=%1$s", serverLauncher.getEvictionHeapPercentage())); expectedCommandLineElements .add("-d" + DistributionConfig.GEMFIRE_PREFIX + "" + START_DEV_REST_API + "=" + "true"); expectedCommandLineElements .add("-d" + DistributionConfig.GEMFIRE_PREFIX + "" + HTTP_SERVICE_PORT + "=" + "8080"); expectedCommandLineElements.add("-d" + DistributionConfig.GEMFIRE_PREFIX + "" + HTTP_SERVICE_BIND_ADDRESS + "=" + "localhost"); for (String commandLineElement : commandLineElements) { expectedCommandLineElements.remove(commandLineElement.toLowerCase()); } assertTrue(String.format("Expected ([]); but was (%1$s)", expectedCommandLineElements), expectedCommandLineElements.isEmpty()); } @Test public void testReadPidWithNonExistingFile() { assertEquals(LauncherLifecycleCommands.INVALID_PID, getLauncherLifecycleCommands().readPid(new File("/path/to/non_existing/pid.file"))); } private LauncherLifecycleCommands getLauncherLifecycleCommands() { return launcherCommands; } private String toClasspath(final String... jarFilePathnames) { String classpath = StringUtils.EMPTY_STRING; if (jarFilePathnames != null) { for (final String jarFilePathname : jarFilePathnames) { classpath += (classpath.isEmpty() ? StringUtils.EMPTY_STRING : File.pathSeparator); classpath += jarFilePathname; } } return classpath; } private String toPath(Object... pathElements) { String path = ""; for (Object pathElement : pathElements) { path += (path.isEmpty() ? StringUtils.EMPTY_STRING : File.pathSeparator); path += pathElement; } return path; } }