You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@geode.apache.org by kl...@apache.org on 2017/10/19 17:13:22 UTC
[geode] 01/04: GEODE-3866: add integration tests for deprecated
launchers
This is an automated email from the ASF dual-hosted git repository.
klund pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/geode.git
commit bbcfb832f32f97f58a4417686f3d6787a8fda136
Author: Kirk Lund <kl...@apache.org>
AuthorDate: Wed Oct 18 12:31:08 2017 -0700
GEODE-3866: add integration tests for deprecated launchers
---
.../DeprecatedAgentLauncherIntegrationTest.java | 294 ++++++++++
...precatedCacheServerLauncherIntegrationTest.java | 618 +++++++++++++++++++++
2 files changed, 912 insertions(+)
diff --git a/geode-core/src/test/java/org/apache/geode/admin/jmx/internal/DeprecatedAgentLauncherIntegrationTest.java b/geode-core/src/test/java/org/apache/geode/admin/jmx/internal/DeprecatedAgentLauncherIntegrationTest.java
new file mode 100644
index 0000000..084e758
--- /dev/null
+++ b/geode-core/src/test/java/org/apache/geode/admin/jmx/internal/DeprecatedAgentLauncherIntegrationTest.java
@@ -0,0 +1,294 @@
+/*
+ * 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.admin.jmx.internal;
+
+import static org.apache.geode.admin.jmx.internal.AgentLauncher.RUNNING;
+import static org.apache.geode.admin.jmx.internal.AgentLauncher.SHUTDOWN;
+import static org.apache.geode.admin.jmx.internal.AgentLauncher.STARTING;
+import static org.apache.geode.internal.i18n.LocalizedStrings.AgentLauncher_0_IS_NOT_RUNNING_IN_SPECIFIED_WORKING_DIRECTORY_1;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.junit.Assume.assumeFalse;
+
+import java.io.File;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.contrib.java.lang.system.RestoreSystemProperties;
+import org.junit.experimental.categories.Category;
+import org.junit.rules.TestName;
+
+import org.apache.geode.admin.jmx.AgentConfig;
+import org.apache.geode.admin.jmx.internal.AgentLauncher.Status;
+import org.apache.geode.internal.lang.SystemUtils;
+import org.apache.geode.test.junit.categories.IntegrationTest;
+import org.apache.geode.test.process.ProcessWrapper;
+
+@Category(IntegrationTest.class)
+public class DeprecatedAgentLauncherIntegrationTest {
+
+ private String classpath;
+
+ @Rule
+ public RestoreSystemProperties restoreSystemProperties = new RestoreSystemProperties();
+
+ @Rule
+ public TestName testName = new TestName();
+
+ @Before
+ public void setUp() throws Exception {
+ assumeFalse(SystemUtils.isWindows());
+
+ this.classpath = System.getProperty("java.class.path");
+ assertThat(this.classpath).isNotEmpty();
+ }
+
+ @Test
+ public void testGetStartOptions() throws Exception {
+ final String[] commandLineArguments = {"start", "appendto-log-file=true", "log-level=warn",
+ "mcast-port=0", "-dir=" + System.getProperty("user.home"), "-J-Xms256M", "-J-Xmx1024M"};
+
+ final AgentLauncher launcher = new AgentLauncher("Agent");
+
+ final Map<String, Object> startOptions = launcher.getStartOptions(commandLineArguments);
+
+ assertThat(startOptions).isNotNull();
+ assertThat(startOptions.get(AgentLauncher.APPENDTO_LOG_FILE)).isEqualTo("true");
+ assertThat(startOptions.get(AgentLauncher.DIR))
+ .isEqualTo(new File(System.getProperty("user.home")));
+
+ final Properties props = (Properties) startOptions.get(AgentLauncher.AGENT_PROPS);
+
+ assertThat(props).isNotNull();
+ assertThat(props).hasSize(2);
+ assertThat(props.getProperty("log-level")).isEqualTo("warn");
+ assertThat(props.getProperty("mcast-port")).isEqualTo("0");
+
+ final List<String> vmArgs = (List<String>) startOptions.get(AgentLauncher.VMARGS);
+
+ assertThat(vmArgs).isNotNull();
+ assertThat(vmArgs).hasSize(2);
+ assertThat(vmArgs).contains("-Xms256M");
+ assertThat(vmArgs).contains("-Xmx1024M");
+
+ // now assert the System property 'gfAgentPropertyFile'
+ assertThat(System.getProperty(AgentConfigImpl.AGENT_PROPSFILE_PROPERTY_NAME)).isEqualTo(
+ new File(System.getProperty("user.home"), AgentConfig.DEFAULT_PROPERTY_FILE).getPath());
+ }
+
+ /**
+ * Test to verify fix for TRAC #44658.
+ * <p>
+ *
+ * TRAC #44658: Agent ignores 'property-file' command line option (regression in 6.6.2)
+ */
+ @Test
+ public void testGetStartOptionsWithPropertyFileOption() throws Exception {
+ final String[] commandLineArguments =
+ {"start", "-dir=" + System.getProperty("user.dir"), "-J-Xms512M", "log-level=warn",
+ "mcast-port=0", "property-file=/path/to/custom/property/file.properties",};
+
+ final AgentLauncher launcher = new AgentLauncher("Agent");
+
+ final Map<String, Object> startOptions = launcher.getStartOptions(commandLineArguments);
+
+ assertThat(startOptions).isNotNull();
+ assertThat(startOptions).isNotEmpty();
+ assertThat(startOptions.get(AgentLauncher.DIR))
+ .isEqualTo(new File(System.getProperty("user.dir")));
+
+ final Properties props = (Properties) startOptions.get(AgentLauncher.AGENT_PROPS);
+
+ assertThat(props).isNotNull();
+ assertThat(props).hasSize(3);
+ assertThat(props.getProperty("log-level")).isEqualTo("warn");
+ assertThat(props.getProperty("mcast-port")).isEqualTo("0");
+ assertThat(props.getProperty(AgentConfigImpl.PROPERTY_FILE_NAME))
+ .isEqualTo("/path/to/custom/property/file.properties");
+
+ final List<String> vmArgs = (List<String>) startOptions.get(AgentLauncher.VMARGS);
+
+ assertThat(vmArgs).isNotNull();
+ assertThat(vmArgs).hasSize(1);
+ assertThat(vmArgs).contains("-Xms512M");
+
+ // now assert the System property 'gfAgentPropertyFile'
+ assertThat(System.getProperty(AgentConfigImpl.AGENT_PROPSFILE_PROPERTY_NAME))
+ .isEqualTo("/path/to/custom/property/file.properties");
+ }
+
+ @Test
+ public void testGetStopOptions() throws Exception {
+ final String[] commandLineArguments = {"stop", "-dir=" + System.getProperty("user.home")};
+
+ final AgentLauncher launcher = new AgentLauncher("Agent");
+
+ final Map<String, Object> stopOptions = launcher.getStopOptions(commandLineArguments);
+
+ assertThat(stopOptions).isNotNull();
+ assertThat(stopOptions.get(AgentLauncher.DIR))
+ .isEqualTo(new File(System.getProperty("user.home")));
+ }
+
+ @Test
+ public void testCreateStatus() throws Exception {
+ final Status status = AgentLauncher.createStatus("agent", RUNNING, 12345);
+
+ assertThat(status).isNotNull();
+ assertThat(status.baseName).isEqualTo("agent");
+ assertThat(status.state).isEqualTo(RUNNING);
+ assertThat(status.pid).isEqualTo(12345);
+ assertThat(status.msg).isNull();
+ assertThat(status.exception).isNull();
+ }
+
+ @Test
+ public void testCreateStatusWithMessageAndException() throws Exception {
+ final Status status = AgentLauncher.createStatus("agent", STARTING, 11235, "Test Message!",
+ new Exception("Test Exception!"));
+
+ assertThat(status).isNotNull();
+ assertThat(status.baseName).isEqualTo("agent");
+ assertThat(status.state).isEqualTo(STARTING);
+ assertThat(status.pid).isEqualTo(11235);
+ assertThat(status.msg).isEqualTo("Test Message!");
+ assertThat(status.exception.getMessage()).isEqualTo("Test Exception!");
+ }
+
+ @Test
+ public void testGetStatusWhenStatusFileDoesNotExists() throws Exception {
+ final AgentLauncher launcher = new AgentLauncher("Agent");
+
+ final Status status = launcher.getStatus();
+
+ assertAgentLauncherStatus(status, "Agent", SHUTDOWN, 0);
+ assertThat(status.msg).isEqualTo(AgentLauncher_0_IS_NOT_RUNNING_IN_SPECIFIED_WORKING_DIRECTORY_1
+ .toLocalizedString("Agent", null));
+ assertThat(status.exception).isNull();
+ }
+
+ @Test
+ public void testPause() throws Exception {
+ final long t0 = System.currentTimeMillis();
+ AgentLauncher.pause(100);
+ final long t1 = System.currentTimeMillis();
+ assertThat(t1 - t0).isGreaterThanOrEqualTo(100);
+ }
+
+ @Test
+ public void testStartStatusAndStop() throws Exception {
+ final File agentWorkingDirectory = getAgentWorkingDirectory(testName.getMethodName());
+ final File agentStatusFile = new File(agentWorkingDirectory, ".agent.ser");
+
+ assertThat(deleteAgentWorkingDirectory(agentWorkingDirectory)).isTrue();
+
+ assertThat(agentWorkingDirectory.mkdir()).isTrue();
+
+ assertThat(agentStatusFile).doesNotExist();
+
+ runAgent("Starting JMX Agent with pid: \\d+", "start", "mcast-port=0", "http-enabled=false",
+ "rmi-enabled=false", "snmp-enabled=false", "-classpath=" + this.classpath,
+ "-dir=" + agentWorkingDirectory.getAbsolutePath());
+
+ assertThat(agentStatusFile).exists();
+
+ runAgent("Agent pid: \\d+ status: running", "status",
+ "-dir=" + agentWorkingDirectory.getAbsolutePath());
+
+ runAgent("The Agent has shut down.", "stop", "-dir=" + agentWorkingDirectory.getAbsolutePath());
+
+ assertThat(agentStatusFile).doesNotExist();
+ }
+
+ @Test
+ public void testWriteReadAndDeleteStatus() throws Exception {
+ final File expectedStatusFile = new File(System.getProperty("user.dir"), ".agent.ser");
+ final AgentLauncher launcher = new AgentLauncher("Agent");
+
+ launcher.getStartOptions(new String[] {"-dir=" + System.getProperty("user.dir")});
+
+ assertThat(expectedStatusFile).doesNotExist();
+
+ final AgentLauncher.Status expectedStatus = AgentLauncher.createStatus("agent", RUNNING, 13579);
+
+ assertAgentLauncherStatus(expectedStatus, "agent", RUNNING, 13579);
+
+ launcher.writeStatus(expectedStatus);
+
+ assertThat(expectedStatusFile).exists();
+
+ final AgentLauncher.Status actualStatus = launcher.readStatus();
+
+ assertThat(actualStatus).isNotNull();
+ assertAgentLauncherStatusEquals(expectedStatus, actualStatus);
+ assertThat(expectedStatusFile).exists();
+
+ launcher.deleteStatus();
+
+ assertThat(expectedStatusFile).doesNotExist();
+ }
+
+ private void assertAgentLauncherStatusEquals(final AgentLauncher.Status expected,
+ final AgentLauncher.Status actual) {
+ assertThat(actual.baseName).isEqualTo(expected.baseName);
+ assertThat(actual.state).isEqualTo(expected.state);
+ assertThat(actual.pid).isEqualTo(expected.pid);
+ }
+
+ private void assertAgentLauncherStatus(final AgentLauncher.Status actual,
+ final String expectedBasename, final int expectedState, final int expectedPid) {
+ assertThat(actual).isNotNull();
+ assertThat(actual.baseName).isEqualTo(expectedBasename);
+ assertThat(actual.state).isEqualTo(expectedState);
+ assertThat(actual.pid).isEqualTo(expectedPid);
+ }
+
+ private static boolean deleteAgentWorkingDirectory(final File agentWorkingDirectory) {
+ return (!agentWorkingDirectory.exists() || deleteFileRecursive(agentWorkingDirectory));
+ }
+
+ private static boolean deleteFileRecursive(final File file) {
+ boolean result = true;
+
+ if (file.isDirectory()) {
+ for (final File childFile : file.listFiles()) {
+ result &= deleteFileRecursive(childFile);
+ }
+ }
+
+ return (result && file.delete());
+ }
+
+ private static File getAgentWorkingDirectory(final String testCaseName) {
+ return new File("AgentLauncherTest_" + testCaseName);
+ }
+
+ private static void runAgent(final String processOutputPattern, final String... args)
+ throws Exception {
+ final ProcessWrapper agentProcess =
+ new ProcessWrapper.Builder().mainClass(AgentLauncher.class).mainArguments(args).build();
+
+ agentProcess.execute();
+
+ if (processOutputPattern != null) {
+ agentProcess.waitForOutputToMatch(processOutputPattern);
+ }
+ agentProcess.waitFor();
+ }
+
+}
diff --git a/geode-core/src/test/java/org/apache/geode/internal/cache/DeprecatedCacheServerLauncherIntegrationTest.java b/geode-core/src/test/java/org/apache/geode/internal/cache/DeprecatedCacheServerLauncherIntegrationTest.java
new file mode 100755
index 0000000..35f77a9
--- /dev/null
+++ b/geode-core/src/test/java/org/apache/geode/internal/cache/DeprecatedCacheServerLauncherIntegrationTest.java
@@ -0,0 +1,618 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more contributor license
+ * agreements. See the NOTICE file distributed with this work for additional information regarding
+ * copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the License. You may obtain a
+ * copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package org.apache.geode.internal.cache;
+
+import static java.util.concurrent.TimeUnit.MINUTES;
+import static org.apache.geode.internal.AvailablePortHelper.getRandomAvailableTCPPorts;
+import static org.apache.geode.internal.cache.xmlcache.CacheXml.GEODE_NAMESPACE;
+import static org.apache.geode.internal.cache.xmlcache.CacheXml.LATEST_SCHEMA_LOCATION;
+import static org.apache.geode.internal.process.ProcessUtils.isProcessAlive;
+import static org.apache.geode.test.dunit.Disconnect.disconnectAllFromDS;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.awaitility.Awaitility.await;
+import static org.junit.Assume.assumeFalse;
+
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
+import java.rmi.AlreadyBoundException;
+import java.rmi.NoSuchObjectException;
+import java.rmi.NotBoundException;
+import java.rmi.Remote;
+import java.rmi.RemoteException;
+import java.rmi.registry.LocateRegistry;
+import java.rmi.registry.Registry;
+import java.rmi.server.UnicastRemoteObject;
+import java.util.List;
+import java.util.Properties;
+import java.util.concurrent.TimeoutException;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.apache.logging.log4j.Logger;
+import org.junit.After;
+import org.junit.AfterClass;
+import org.junit.Before;
+import org.junit.Ignore;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+import org.junit.rules.TemporaryFolder;
+import org.junit.rules.TestName;
+
+import org.apache.geode.InternalGemFireError;
+import org.apache.geode.cache.Declarable;
+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.PoolManager;
+import org.apache.geode.cache.util.CacheListenerAdapter;
+import org.apache.geode.distributed.Locator;
+import org.apache.geode.internal.PureJavaMode;
+import org.apache.geode.internal.cache.control.InternalResourceManager;
+import org.apache.geode.internal.cache.control.InternalResourceManager.ResourceObserverAdapter;
+import org.apache.geode.internal.cache.xmlcache.CacheXml;
+import org.apache.geode.internal.logging.LogService;
+import org.apache.geode.test.junit.categories.IntegrationTest;
+import org.apache.geode.test.process.ProcessWrapper;
+
+/**
+ * Tests the CacheServerLauncher. Extracted/renamed from CacheServerLauncherDUnitTest.
+ *
+ * @since GemFire 6.0
+ */
+@Category(IntegrationTest.class)
+public class DeprecatedCacheServerLauncherIntegrationTest {
+ private static final Logger logger = LogService.getLogger();
+
+ private static final String CLASSNAME =
+ DeprecatedCacheServerLauncherIntegrationTest.class.getSimpleName();
+ private static final String CONTROLLER_NAMING_PORT_PROP = CLASSNAME + ".controllerNamingPort";
+ private static final String CACHESERVER_NAMING_PORT_PROP = CLASSNAME + ".cacheServerNamingPort";
+ private static final String REBALANCE_STATUS_BINDING = CLASSNAME + ".REBALANCE_STATUS_BINDING";
+ private static final String FAIL_SAFE_BINDING = CLASSNAME + ".FAIL_SAFE_BINDING";
+
+ private String classpath;
+
+ private int serverPort;
+
+ private int controllerNamingPort;
+ private int cacheServerNamingPort;
+ private int commandPort;
+ private int xmlPort;
+
+ private File directory;
+ private File logFile;
+ private File cacheXmlFile;
+
+ private String directoryPath;
+ private String logFileName;
+ private String cacheXmlFileName;
+
+ private Registry registry;
+ private RebalanceStatus status;
+
+ private ProcessWrapper processWrapper;
+
+ @Rule
+ public TemporaryFolder temporaryFolder = new TemporaryFolder();
+
+ @Rule
+ public TestName testName = new TestName();
+
+ @Before
+ public void setUp() throws Exception {
+ this.classpath = System.getProperty("java.class.path");
+ assertThat(this.classpath).isNotEmpty();
+
+ this.directory = this.temporaryFolder.getRoot();
+ this.directoryPath = this.directory.getAbsolutePath();
+ this.logFileName = this.testName.getMethodName() + ".log";
+ this.cacheXmlFileName = this.testName.getMethodName() + ".xml";
+
+ this.cacheXmlFile = new File(this.directory, this.cacheXmlFileName);
+ this.logFile = new File(this.directory, this.logFileName);
+
+ int[] tcpPorts = getRandomAvailableTCPPorts(5);
+ this.serverPort = tcpPorts[0];
+ this.controllerNamingPort = tcpPorts[1];
+ this.cacheServerNamingPort = tcpPorts[2];
+ this.commandPort = tcpPorts[3];
+ this.xmlPort = tcpPorts[4];
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ disconnectAllFromDS();
+
+ invokeFailSafe();
+
+ unexportObject(this.status);
+ unexportObject(this.registry);
+ destroy(this.processWrapper);
+ }
+
+ @AfterClass
+ public static void afterClass() throws Exception {
+ if (Locator.hasLocator()) {
+ Locator.getLocator().stop();
+ }
+ }
+
+ @Test
+ public void testStartStatusStop() throws Exception {
+ createCacheXml(this.directory, this.cacheXmlFileName, this.serverPort);
+
+ execAndValidate("CacheServer pid: \\d+ status: running", "start",
+ "-J-D" + CONTROLLER_NAMING_PORT_PROP + "=" + this.controllerNamingPort,
+ "-J-D" + CACHESERVER_NAMING_PORT_PROP + "=" + this.cacheServerNamingPort,
+ "-J-Xmx" + Runtime.getRuntime().maxMemory(), "-J-Dgemfire.use-cluster-configuration=false",
+ "-J-Dgemfire.locators=\"\"", "log-file=" + this.logFileName,
+ "cache-xml-file=" + this.cacheXmlFileName, "-dir=" + this.directoryPath,
+ "-classpath=" + this.classpath);
+
+ execAndValidate("CacheServer pid: \\d+ status: running", "status",
+ "-dir=" + this.directoryPath);
+
+ execAndValidate(".*The CacheServer has stopped\\.", "stop", "-dir=" + this.directoryPath);
+ }
+
+ @Test
+ public void testStartWithExistingCacheServerDotSerFileCheckStatusAndStop() throws Exception {
+ File cacheServerDotSerFile = createCacheServerSerFile(this.directory);
+
+ createCacheXml(this.directory, this.cacheXmlFileName, this.serverPort, 0);
+
+ execAndValidate("CacheServer pid: \\d+ status: running", "start",
+ "cache-xml-file=" + this.cacheXmlFile.getAbsolutePath(),
+ "log-file=" + this.logFile.getAbsolutePath(), "-J-Dgemfire.use-cluster-configuration=false",
+ "-J-Dgemfire.locators=\"\"", "-server-port=" + this.serverPort,
+ "-dir=" + this.directory.getAbsolutePath(), "-classpath=" + this.classpath);
+
+ execAndValidate("CacheServer pid: \\d+ status: running", "status",
+ "-dir=" + this.directory.getAbsolutePath());
+
+ execAndValidate(".*The CacheServer has stopped\\.", "stop",
+ "-dir=" + this.directory.getAbsolutePath());
+
+ await().atMost(2, MINUTES).until(() -> assertThat(cacheServerDotSerFile).doesNotExist());
+ }
+
+ @Ignore("This test needs to be reworked")
+ @Test
+ public void testCacheServerTerminatingAbnormally() throws Exception {
+ assumeFalse(PureJavaMode.isPure());
+
+ createCacheXml(this.directory, this.cacheXmlFileName, this.serverPort, 0);
+
+ this.processWrapper = new ProcessWrapper.Builder().mainClass(CacheServerLauncher.class)
+ .mainArguments(new String[] {"start", "cache-xml-file=" + this.cacheXmlFileName,
+ "log-file=" + this.logFileName, "log-level=info",
+ "-J-Dgemfire.use-cluster-configuration=false", "-J-Dgemfire.locators=\"\"",
+ "-server-port=" + this.serverPort, "-dir=" + this.directoryPath,
+ "-classpath=" + this.classpath})
+ .build();
+
+ this.processWrapper.execute();
+ this.processWrapper.waitForOutputToMatch("CacheServer pid: \\d+ status: running");
+ this.processWrapper.waitFor();
+ String processOutput = this.processWrapper.getOutput();
+
+ Matcher matcher = Pattern.compile("\\d+").matcher(processOutput);
+ assertThat(matcher.find()).isTrue();
+ assertThat(matcher.find()).isTrue();
+ String pidString = matcher.group();
+ int pid = Integer.parseInt(pidString);
+
+ assertThat(isProcessAlive(pid)).isTrue();
+
+ // now, we will forcefully kill the CacheServer process
+ invokeFailSafe();
+
+ await().atMost(2, MINUTES)
+ .until(() -> assertThat(this.processWrapper.getProcess().isAlive()).isFalse());
+
+ await().atMost(2, MINUTES).until(() -> assertThat(isProcessAlive(pid)).isFalse());
+
+ File dotCacheServerDotSerFile = new File(this.directory, ".cacheserver.ser");
+
+ // assert that the .cacheserver.ser file remains...
+ assertThat(dotCacheServerDotSerFile).exists();
+
+ await().atMost(2, MINUTES)
+ .until(() -> execAndWaitForOutputToMatch("CacheServer pid: " + pid + " status: stopped",
+ "status", "-dir=" + this.directory.getName()));
+
+ assertThat(this.processWrapper.getOutput()).isNull();
+
+ execAndValidate("The CacheServer has stopped.", "stop", "-dir=" + this.directory.getName());
+
+ execAndValidate("CacheServer pid: 0 status: stopped", "status",
+ "-dir=" + this.directory.getName());
+
+ assertThat(dotCacheServerDotSerFile).doesNotExist();
+ }
+
+ @Test
+ public void testRebalance() throws Exception {
+ this.registry = LocateRegistry.createRegistry(this.controllerNamingPort);
+ this.status = new RebalanceStatus();
+ this.registry.bind(REBALANCE_STATUS_BINDING, this.status);
+
+ createCacheXml(this.directory, this.cacheXmlFileName, this.serverPort);
+
+ execAndValidate("CacheServer pid: \\d+ status: running", "start",
+ "-J-D" + CONTROLLER_NAMING_PORT_PROP + "=" + this.controllerNamingPort,
+ "-J-D" + CACHESERVER_NAMING_PORT_PROP + "=" + this.cacheServerNamingPort,
+ "-J-Xmx" + Runtime.getRuntime().maxMemory(), "-J-Dgemfire.use-cluster-configuration=false",
+ "-J-Dgemfire.locators=\"\"", "log-file=" + this.logFileName,
+ "cache-xml-file=" + this.cacheXmlFileName, "-dir=" + this.directoryPath,
+ "-classpath=" + this.classpath, "-rebalance");
+
+ await().atMost(2, MINUTES).until(() -> assertThat(this.status.isStarted()).isTrue());
+ await().atMost(2, MINUTES).until(() -> assertThat(this.status.isFinished()).isTrue());
+
+ execAndValidate("CacheServer pid: \\d+ status: running", "status", "-dir=" + this.directory);
+
+ execAndValidate(".*The CacheServer has stopped\\.", "stop", "-dir=" + this.directory);
+ }
+
+ @Test
+ public void testCreateBuckets() throws Exception {
+ this.registry = LocateRegistry.createRegistry(this.controllerNamingPort);
+ this.status = new RebalanceStatus();
+ this.registry.bind(REBALANCE_STATUS_BINDING, this.status);
+
+ createCacheXml(this.directory, this.cacheXmlFileName, this.serverPort);
+
+ execAndValidate("CacheServer pid: \\d+ status: running", "start",
+ "-J-D" + CONTROLLER_NAMING_PORT_PROP + "=" + this.controllerNamingPort,
+ "-J-D" + CACHESERVER_NAMING_PORT_PROP + "=" + this.cacheServerNamingPort,
+ "-J-D" + CacheServerLauncher.ASSIGN_BUCKETS + "=true",
+ "-J-Xmx" + Runtime.getRuntime().maxMemory(), "-J-Dgemfire.use-cluster-configuration=false",
+ "-J-Dgemfire.locators=\"\"", "log-file=" + this.logFileName,
+ "cache-xml-file=" + this.cacheXmlFileName, "-dir=" + this.directoryPath,
+ "-classpath=" + this.classpath, "-rebalance");
+
+ await().atMost(2, MINUTES).until(() -> assertThat(this.status.isStarted()).isTrue());
+ await().atMost(2, MINUTES).until(() -> assertThat(this.status.isFinished()).isTrue());
+
+ execAndValidate("CacheServer pid: \\d+ status: running", "status", "-dir=" + this.directory);
+
+ execAndValidate(".*The CacheServer has stopped\\.", "stop", "-dir=" + this.directory);
+ }
+
+ @Test
+ public void testWithoutServerPort() throws Exception {
+ createCacheXml(this.directory, this.cacheXmlFileName, this.xmlPort, 1);
+
+ execAndValidate("CacheServer pid: \\d+ status: running", "start",
+ "-J-D" + CONTROLLER_NAMING_PORT_PROP + "=" + this.controllerNamingPort,
+ "-J-D" + CACHESERVER_NAMING_PORT_PROP + "=" + this.cacheServerNamingPort,
+ "-J-Xmx" + Runtime.getRuntime().maxMemory(), "-J-Dgemfire.use-cluster-configuration=false",
+ "-J-Dgemfire.locators=\"\"", "log-file=" + this.logFileName,
+ "cache-xml-file=" + this.cacheXmlFileName, "-dir=" + this.directoryPath,
+ "-classpath=" + this.classpath);
+
+ execAndValidate("CacheServer pid: \\d+ status: running", "status", "-dir=" + this.directory);
+
+ ClientCache cache = new ClientCacheFactory().create();
+ ClientRegionFactory<Integer, Integer> regionFactory =
+ cache.createClientRegionFactory(ClientRegionShortcut.PROXY);
+ Pool pool = PoolManager.createFactory().addServer("localhost", this.xmlPort).create("cslPool");
+ regionFactory.setPoolName(pool.getName());
+ Region<Integer, Integer> region = regionFactory.create("rgn");
+ List<InetSocketAddress> servers = pool.getServers();
+
+ assertThat(servers).hasSize(1);
+ assertThat(servers.iterator().next().getPort()).isEqualTo(this.xmlPort);
+
+ region.put(1, 1); // put should be successful
+
+ execAndValidate("The CacheServer has stopped\\.", "stop", "-dir=" + this.directory);
+ }
+
+ @Test
+ public void testServerPortOneCacheServer() throws Exception {
+ createCacheXml(this.directory, this.cacheXmlFileName, this.xmlPort, 1);
+
+ execAndValidate("CacheServer pid: \\d+ status: running", "start",
+ "-J-D" + CONTROLLER_NAMING_PORT_PROP + "=" + this.controllerNamingPort,
+ "-J-D" + CACHESERVER_NAMING_PORT_PROP + "=" + this.cacheServerNamingPort,
+ "-J-Xmx" + Runtime.getRuntime().maxMemory(), "-J-Dgemfire.use-cluster-configuration=false",
+ "-J-Dgemfire.locators=\"\"", "log-file=" + this.logFileName,
+ "cache-xml-file=" + this.cacheXmlFileName, "-dir=" + this.directoryPath,
+ "-classpath=" + this.classpath, "-server-port=" + this.commandPort);
+
+ execAndValidate("CacheServer pid: \\d+ status: running", "status", "-dir=" + this.directory);
+
+ ClientCache cache = new ClientCacheFactory().create();
+
+ ClientRegionFactory<Integer, Integer> regionFactory =
+ cache.createClientRegionFactory(ClientRegionShortcut.PROXY);
+ Pool pool =
+ PoolManager.createFactory().addServer("localhost", this.commandPort).create("cslPool");
+ regionFactory.setPoolName(pool.getName());
+ Region<Integer, Integer> region = regionFactory.create("rgn");
+ List<InetSocketAddress> servers = pool.getServers();
+
+ assertThat(servers).hasSize(1);
+ assertThat(servers.iterator().next().getPort()).isEqualTo(this.commandPort);
+
+ region.put(1, 1); // put should be successful
+
+ execAndValidate("The CacheServer has stopped\\.", "stop", "-dir=" + this.directory);
+ }
+
+ @Test
+ public void testServerPortNoCacheServer() throws Exception {
+ createCacheXml(this.directory, this.cacheXmlFileName, 0, 0);
+
+ execAndValidate("CacheServer pid: \\d+ status: running", "start",
+ "-J-D" + CONTROLLER_NAMING_PORT_PROP + "=" + this.controllerNamingPort,
+ "-J-D" + CACHESERVER_NAMING_PORT_PROP + "=" + this.cacheServerNamingPort,
+ "-J-Xmx" + Runtime.getRuntime().maxMemory(), "-J-Dgemfire.use-cluster-configuration=false",
+ "-J-Dgemfire.locators=\"\"", "log-file=" + this.logFileName,
+ "cache-xml-file=" + this.cacheXmlFileName, "-dir=" + this.directoryPath,
+ "-classpath=" + this.classpath, "-server-port=" + this.commandPort,
+ "-server-bind-address=" + InetAddress.getLocalHost().getHostName());
+
+ execAndValidate("CacheServer pid: \\d+ status: running", "status", "-dir=" + this.directory);
+
+ ClientCache cache = new ClientCacheFactory().create();
+ ClientRegionFactory<Integer, Integer> regionFactory =
+ cache.createClientRegionFactory(ClientRegionShortcut.PROXY);
+ Pool pool = PoolManager.createFactory()
+ .addServer(InetAddress.getLocalHost().getHostName(), this.commandPort).create("cslPool");
+ regionFactory.setPoolName(pool.getName());
+ Region<Integer, Integer> region = regionFactory.create("rgn");
+ List<InetSocketAddress> servers = pool.getServers();
+
+ assertThat(servers).hasSize(1);
+ assertThat(servers.iterator().next().getPort()).isEqualTo(this.commandPort);
+
+ region.put(1, 1); // put should be successful
+
+ execAndValidate("The CacheServer has stopped\\.", "stop", "-dir=" + this.directory);
+ }
+
+ private void unexportObject(final Remote object) {
+ if (object == null) {
+ return;
+ }
+ try {
+ UnicastRemoteObject.unexportObject(object, true);
+ } catch (NoSuchObjectException ignore) {
+ }
+ }
+
+ private void destroy(final ProcessWrapper processWrapper) {
+ if (processWrapper == null) {
+ return;
+ }
+ processWrapper.destroy();
+ }
+
+ private File createCacheServerSerFile(final File directory) throws Exception {
+ File cacheServerSerFile = new File(directory, ".cacheserver.ser");
+ assertThat(cacheServerSerFile.createNewFile()).isTrue();
+ return cacheServerSerFile;
+ }
+
+ private void invokeFailSafe() {
+ try {
+ Registry registry = LocateRegistry.getRegistry(this.cacheServerNamingPort);
+ FailSafeRemote failSafe = (FailSafeRemote) registry.lookup(FAIL_SAFE_BINDING);
+ failSafe.kill();
+ } catch (RemoteException | NotBoundException ignore) {
+ // cacheserver was probably stopped already
+ }
+ }
+
+ private void execAndValidate(final String regex, final String... args)
+ throws InterruptedException, TimeoutException {
+ ProcessWrapper processWrapper = new ProcessWrapper.Builder()
+ .mainClass(CacheServerLauncher.class).mainArguments(args).build();
+ processWrapper.execute();
+ if (regex != null) {
+ processWrapper.waitForOutputToMatch(regex, 2 * 60 * 1000);
+ }
+ processWrapper.waitFor();
+ }
+
+ private boolean execAndWaitForOutputToMatch(final String regex, final String... args) {
+ ProcessWrapper processWrapper = new ProcessWrapper.Builder()
+ .mainClass(CacheServerLauncher.class).mainArguments(args).build();
+ try {
+ processWrapper.execute();
+ } catch (InterruptedException | TimeoutException e) {
+ throw new AssertionError(e);
+ }
+ Pattern pattern = Pattern.compile(regex);
+ return pattern.matcher(processWrapper.getOutput(true)).matches();
+ }
+
+ private void createCacheXml(final File dir, final String cacheXmlName, final int port)
+ throws IOException {
+ File file = new File(dir, cacheXmlName);
+ assertThat(file.createNewFile()).isTrue();
+
+ try (FileWriter writer = new FileWriter(file)) {
+ writer.write("<?xml version=\"1.0\"?>\n");
+ writer.write("<cache\n");
+ writer.write(" xmlns=\"" + GEODE_NAMESPACE + "\"");
+ writer.write(" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"");
+ writer.write(
+ " xsi:schemaLocation=\"" + GEODE_NAMESPACE + " " + LATEST_SCHEMA_LOCATION + "\"");
+ writer.write(" version=\"" + CacheXml.VERSION_LATEST + "\">");
+ writer.write(" <cache-server port=\"" + port + "\" notify-by-subscription=\"false\"/>\n");
+ writer.write(" <region name=\"PartitionedRegion\">\n");
+ writer.write(" <region-attributes>\n");
+ writer.write(" <partition-attributes redundant-copies=\"0\"/>\n");
+ writer.write(" <cache-listener>\n");
+ writer
+ .write(" <class-name>" + SpecialCacheListener.class.getName() + "</class-name>\n");
+ writer.write(" </cache-listener>\n");
+
+ writer.write(" </region-attributes>\n");
+ writer.write(" </region>\n");
+ writer.write("</cache>\n");
+
+ writer.flush();
+ }
+ }
+
+ private void createCacheXml(final File dir, final String cacheXmlName, final int port,
+ final int numServers) throws IOException {
+ File file = new File(dir, cacheXmlName);
+ assertThat(file.createNewFile()).isTrue();
+
+ try (FileWriter writer = new FileWriter(file)) {
+ writer.write("<?xml version=\"1.0\"?>\n");
+ writer.write("<cache\n");
+ writer.write(" xmlns=\"" + GEODE_NAMESPACE + "\"");
+ writer.write(" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"");
+ writer.write(
+ " xsi:schemaLocation=\"" + GEODE_NAMESPACE + " " + LATEST_SCHEMA_LOCATION + "\"");
+ writer.write(" version=\"" + CacheXml.VERSION_LATEST + "\">");
+ for (int i = 0; i < numServers; i++) {
+ writer.write(" <cache-server port=\"" + port + "\"");
+ writer.write("/>\n");
+ }
+ writer.write("<region name=\"rgn\" />\n");
+ writer.write("</cache>\n");
+ writer.flush();
+ }
+ }
+
+ public static class SpecialCacheListener<K, V> extends CacheListenerAdapter<K, V>
+ implements Declarable {
+
+ private static final int CONTROLLER_NAMING_PORT =
+ Integer.getInteger(CONTROLLER_NAMING_PORT_PROP);
+
+ private static final int CACHESERVER_NAMING_PORT =
+ Integer.getInteger(CACHESERVER_NAMING_PORT_PROP);
+
+ public SpecialCacheListener() {
+ try {
+ Registry registry = LocateRegistry.createRegistry(CACHESERVER_NAMING_PORT);
+ FailSafe failsafe = new FailSafe();
+ registry.bind(FAIL_SAFE_BINDING, failsafe);
+ } catch (RemoteException | AlreadyBoundException e) {
+ throw new InternalGemFireError(e);
+ }
+
+ InternalResourceManager.setResourceObserver(new ResourceObserverAdapter() {
+ @Override
+ public void rebalancingOrRecoveryStarted(final Region region) {
+ try {
+ logger.info("SpecialCacheListener#rebalancingStarted on {}", region);
+ Registry registry = LocateRegistry.getRegistry(CONTROLLER_NAMING_PORT);
+ RebalanceStatusRemote status =
+ (RebalanceStatusRemote) registry.lookup(REBALANCE_STATUS_BINDING);
+ if (region.getName().contains("PartitionedRegion")) {
+ status.rebalancingStarted();
+ }
+ } catch (RemoteException | NotBoundException e) {
+ throw new InternalGemFireError(e);
+ }
+ }
+
+ @Override
+ public void rebalancingOrRecoveryFinished(final Region region) {
+ try {
+ logger.info("SpecialCacheListener#rebalancingFinished on {}", region);
+ Registry registry = LocateRegistry.getRegistry(CONTROLLER_NAMING_PORT);
+ RebalanceStatusRemote status =
+ (RebalanceStatusRemote) registry.lookup(REBALANCE_STATUS_BINDING);
+ if (region.getName().contains("PartitionedRegion")) {
+ status.rebalancingFinished();
+ }
+ } catch (RemoteException | NotBoundException e) {
+ throw new InternalGemFireError(e);
+ }
+ }
+ });
+ }
+
+ @Override
+ public void init(Properties props) {
+ // do nothing
+ }
+ }
+
+ private interface RebalanceStatusRemote extends Remote {
+ void rebalancingStarted() throws RemoteException;
+
+ void rebalancingFinished() throws RemoteException;
+ }
+
+ private static class RebalanceStatus extends UnicastRemoteObject
+ implements RebalanceStatusRemote {
+ private final Object lock = new Object();
+ private boolean started = false;
+ private boolean finished = false;
+
+ RebalanceStatus() throws RemoteException {
+ super();
+ }
+
+ @Override
+ public void rebalancingStarted() throws RemoteException {
+ synchronized (this.lock) {
+ this.started = true;
+ this.lock.notifyAll();
+ }
+ }
+
+ @Override
+ public void rebalancingFinished() throws RemoteException {
+ synchronized (this.lock) {
+ this.finished = true;
+ this.lock.notifyAll();
+ }
+ }
+
+ boolean isStarted() {
+ return this.started;
+ }
+
+ boolean isFinished() {
+ return this.finished;
+ }
+ }
+
+ private interface FailSafeRemote extends Remote {
+ void kill() throws RemoteException;
+ }
+
+ private static class FailSafe extends UnicastRemoteObject implements FailSafeRemote {
+
+ FailSafe() throws RemoteException {
+ super();
+ }
+
+ @Override
+ public void kill() throws RemoteException {
+ System.exit(0);
+ }
+ }
+}
--
To stop receiving notification emails like this one, please contact
"commits@geode.apache.org" <co...@geode.apache.org>.