SGF-416 - Add additional integration test testing the interaction between a client and server when Pool configuration is used to only initialize the DEFAULT Pool used by the PROXY client Region.

(cherry picked from commit 22dc8a601767fa8ec532b5ca77f0fed2e07320bd)
Signed-off-by: John Blum <jblum@pivotal.io>
This commit is contained in:
John Blum
2016-03-28 14:02:34 -07:00
parent 0820482818
commit 2465e5f678
12 changed files with 248 additions and 85 deletions

View File

@@ -0,0 +1,108 @@
/*
* Copyright 2012 the original author or authors.
*
* Licensed 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.springframework.data.gemfire.client;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.is;
import static org.junit.Assert.assertThat;
import javax.annotation.Resource;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.data.gemfire.process.ProcessWrapper;
import org.springframework.data.gemfire.test.AbstractGemFireClientServerIntegrationTest;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.util.Assert;
import com.gemstone.gemfire.cache.CacheLoader;
import com.gemstone.gemfire.cache.CacheLoaderException;
import com.gemstone.gemfire.cache.LoaderHelper;
import com.gemstone.gemfire.cache.Region;
/**
* The ClientCachePoolTests class...
*
* @author John Blum
* @since 1.0.0
*/
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration
@SuppressWarnings("all")
public class ClientCachePoolTests extends AbstractGemFireClientServerIntegrationTest {
private static ProcessWrapper gemfireServerProcess;
@BeforeClass
public static void setupGemFireServer() throws Exception {
gemfireServerProcess = runGemFireServer(ClientCachePoolTests.class);
}
@AfterClass
public static void tearDownGemFireServer() {
stopGemFireServer(gemfireServerProcess);
}
@Resource(name = "Factorials")
private Region<Long, Long> factorials;
@Test
public void computeFactorials() {
assertThat(factorials.get(0l), is(equalTo(1l)));
assertThat(factorials.get(1l), is(equalTo(1l)));
assertThat(factorials.get(2l), is(equalTo(2l)));
assertThat(factorials.get(3l), is(equalTo(6l)));
assertThat(factorials.get(4l), is(equalTo(24l)));
assertThat(factorials.get(5l), is(equalTo(120l)));
assertThat(factorials.get(6l), is(equalTo(720l)));
assertThat(factorials.get(7l), is(equalTo(5040l)));
assertThat(factorials.get(8l), is(equalTo(40320l)));
assertThat(factorials.get(9l), is(equalTo(362880l)));
}
public static class FactorialsClassLoader implements CacheLoader<Long, Long> {
@Override
public Long load(LoaderHelper<Long, Long> helper) throws CacheLoaderException {
Long number = helper.getKey();
Assert.notNull(number, "number must not be null");
Assert.isTrue(number >= 0, String.format("number [%1$d] must be greater than equal to 0", number));
if (number <= 2l) {
return (number < 2l ? 1l : 2l);
}
long result = number;
while (--number > 1) {
result *= number;
}
return result;
}
@Override
public void close() {
}
}
}

View File

@@ -111,12 +111,12 @@ public class DurableClientCacheIntegrationTest extends AbstractGemFireClientServ
@BeforeClass
public static void setupGemFireServer() throws IOException {
serverProcess = setupGemFireServer(DurableClientCacheIntegrationTest.class);
serverProcess = runGemFireServer(DurableClientCacheIntegrationTest.class);
}
@AfterClass
public static void tearDownGemFireServer() {
tearDownGemFireServer(serverProcess);
stopGemFireServer(serverProcess);
serverProcess = null;
}

View File

@@ -23,6 +23,7 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.springframework.data.gemfire.test.support.FileSystemUtils;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
@@ -44,20 +45,20 @@ public class ProcessConfiguration {
private final Map<String, String> environment;
public static ProcessConfiguration create(final ProcessBuilder processBuilder) {
Assert.notNull(processBuilder, "The ProcessBuilder used to construct, configure and start the Process must not be null!");
public static ProcessConfiguration create(ProcessBuilder processBuilder) {
Assert.notNull(processBuilder, "The ProcessBuilder used to configure and start the Process must not be null!");
return new ProcessConfiguration(processBuilder.command(), processBuilder.directory(),
processBuilder.environment(), processBuilder.redirectErrorStream());
}
public ProcessConfiguration(final List<String> command, final File workingDirectory,
final Map<String, String> environment, final boolean redirectingErrorStream) {
public ProcessConfiguration(List<String> command, File workingDirectory, Map<String, String> environment,
boolean redirectingErrorStream) {
Assert.notEmpty(command, "The command used to run the process must be specified!");
Assert.notEmpty(command, "process command must be specified");
Assert.isTrue((workingDirectory != null && workingDirectory.isDirectory()), String.format(
"The process working directory (%1$s) is not valid!", workingDirectory));
Assert.isTrue(FileSystemUtils.isDirectory(workingDirectory), String.format(
"process working directory [%1$s] is not valid", workingDirectory));
this.command = new ArrayList<String>(command);
this.workingDirectory = workingDirectory;

View File

@@ -83,6 +83,7 @@ public abstract class ProcessExecutor {
command.add(JAVA_EXE.getAbsolutePath());
command.add("-server");
command.add("-ea");
command.add("-classpath");
command.add(StringUtils.hasText(classpath) ? classpath : JAVA_CLASSPATH);
command.addAll(getSpringGemFireSystemProperties());

View File

@@ -69,8 +69,8 @@ public class ProcessWrapper {
private final Process process;
private final ProcessConfiguration processConfiguration;
public ProcessWrapper(final Process process, final ProcessConfiguration processConfiguration) {
Assert.notNull(process, "The Process object backing this wrapper must not be null!");
public ProcessWrapper(Process process, ProcessConfiguration processConfiguration) {
Assert.notNull(process, "Process must not be null");
Assert.notNull(processConfiguration, "The context and configuration meta-data providing details about"
+ " the environment in which the process is running and how the process was configured must not be null!");
@@ -114,9 +114,9 @@ public class ProcessWrapper {
};
}
protected Thread newThread(final String name, final Runnable task) {
Assert.isTrue(!StringUtils.isEmpty(name), "The name of the Thread must be specified!");
Assert.notNull(task, "The Thread task must not be null!");
protected Thread newThread(String name, Runnable task) {
Assert.isTrue(!StringUtils.isEmpty(name), "Thread name must be specified");
Assert.notNull(task, "Thread task must not be null");
Thread thread = new Thread(task, name);
thread.setDaemon(DEFAULT_DAEMON_THREAD);
thread.setPriority(Thread.NORM_PRIORITY);
@@ -153,7 +153,7 @@ public class ProcessWrapper {
}
public boolean isRunning() {
return ProcessUtils.isRunning(this.process);
return ProcessUtils.isRunning(process);
}
public File getWorkingDirectory() {
@@ -193,7 +193,7 @@ public class ProcessWrapper {
return FileUtils.read(log);
}
public boolean register(final ProcessInputStreamListener listener) {
public boolean register(ProcessInputStreamListener listener) {
return (listener != null && listeners.add(listener));
}
@@ -207,7 +207,7 @@ public class ProcessWrapper {
public void signalStop() {
try {
ProcessUtils.signalStop(this.process);
ProcessUtils.signalStop(process);
}
catch (IOException e) {
log.warning("Failed to signal the process to stop!");
@@ -222,8 +222,9 @@ public class ProcessWrapper {
return stop(DEFAULT_WAIT_TIME_MILLISECONDS);
}
public int stop(final long milliseconds) {
public int stop(long milliseconds) {
if (isRunning()) {
boolean interrupted = false;
int exitValue = -1;
final int pid = safeGetPid();
final long timeout = (System.currentTimeMillis() + milliseconds);
@@ -244,9 +245,10 @@ public class ProcessWrapper {
while (!exited.get() && System.currentTimeMillis() < timeout) {
try {
exitValue = futureExitValue.get(milliseconds, TimeUnit.MILLISECONDS);
log.info(String.format("Process [%1$s] has been stopped.%n", pid));
log.info(String.format("Process [%1$s] has stopped.%n", pid));
}
catch (InterruptedException ignore) {
interrupted = true;
}
}
}
@@ -260,6 +262,10 @@ public class ProcessWrapper {
}
finally {
executorService.shutdownNow();
if (interrupted) {
Thread.currentThread().interrupt();
}
}
return exitValue;
@@ -279,7 +285,7 @@ public class ProcessWrapper {
return stop();
}
public boolean unregister(final ProcessInputStreamListener listener) {
public boolean unregister(ProcessInputStreamListener listener) {
return listeners.remove(listener);
}
@@ -287,7 +293,7 @@ public class ProcessWrapper {
waitFor(DEFAULT_WAIT_TIME_MILLISECONDS);
}
public void waitFor(final long milliseconds) {
public void waitFor(long milliseconds) {
ThreadUtils.timedWait(milliseconds, 500, new ThreadUtils.WaitCondition() {
@Override public boolean waiting() {
return isRunning();

View File

@@ -31,6 +31,7 @@ import java.lang.management.RuntimeMXBean;
import java.util.Scanner;
import java.util.logging.Logger;
import org.springframework.data.gemfire.test.support.FileSystemUtils;
import org.springframework.data.gemfire.test.support.IOUtils;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
@@ -73,12 +74,12 @@ public abstract class ProcessUtils {
}
}
throw new PidUnavailableException(String.format("The process ID (PID) is not available (%1$s)!",
throw new PidUnavailableException(String.format("process ID (PID) not available [%1$s]",
runtimeMXBeanName), cause);
}
/*
public static boolean isRunning(final int processId) {
public static boolean isRunning(int processId) {
/*
for (VirtualMachineDescriptor vmDescriptor : VirtualMachine.list()) {
if (String.valueOf(processId).equals(vmDescriptor.id())) {
return true;
@@ -86,10 +87,11 @@ public abstract class ProcessUtils {
}
return false;
*/
throw new UnsupportedOperationException("operation not supported");
}
*/
public static boolean isRunning(final Process process) {
public static boolean isRunning(Process process) {
try {
process.exitValue();
return false;
@@ -99,7 +101,7 @@ public abstract class ProcessUtils {
}
}
public static void signalStop(final Process process) throws IOException {
public static void signalStop(Process process) throws IOException {
if (isRunning(process)) {
OutputStream processOutputStream = process.getOutputStream();
processOutputStream.write(TERM_TOKEN.concat("\n").getBytes());
@@ -107,30 +109,28 @@ public abstract class ProcessUtils {
}
}
@SuppressWarnings("all")
public static void waitForStopSignal() {
Scanner in = new Scanner(System.in);
while (!TERM_TOKEN.equals(in.next()));
}
public static int findAndReadPid(final File workingDirectory) {
Assert.isTrue(workingDirectory != null && workingDirectory.isDirectory(), String.format(
"The file system pathname (%1$s) expected to contain a PID file is not a valid directory!",
workingDirectory));
public static int findAndReadPid(File workingDirectory) {
File pidFile = findPidFile(workingDirectory);
if (pidFile == null) {
throw new PidUnavailableException(String.format(
"No PID file was found in working directory (%1$s) or any of it's sub-directories!",
"no PID file was found in working directory [%1$s] or any of it's sub-directories",
workingDirectory));
}
return readPid(pidFile);
}
protected static File findPidFile(final File workingDirectory) {
Assert.isTrue(workingDirectory != null && workingDirectory.isDirectory(), String.format(
"The file system pathname (%1$s) is not valid directory!", workingDirectory));
@SuppressWarnings("all")
protected static File findPidFile(File workingDirectory) {
Assert.isTrue(FileSystemUtils.isDirectory(workingDirectory), String.format(
"File [%1$s] is not a valid directory", workingDirectory));
for (File file : workingDirectory.listFiles(DirectoryPidFileFilter.INSTANCE)) {
if (file.isDirectory()) {
@@ -145,9 +145,10 @@ public abstract class ProcessUtils {
return null;
}
public static int readPid(final File pidFile) {
@SuppressWarnings("all")
public static int readPid(File pidFile) {
Assert.isTrue(pidFile != null && pidFile.isFile(), String.format(
"The file system pathname (%1$s) is not a valid file!", pidFile));
"File [%1$s] is not a valid file", pidFile));
BufferedReader fileReader = null;
String pidValue = null;
@@ -158,25 +159,26 @@ public abstract class ProcessUtils {
return Integer.parseInt(pidValue);
}
catch (FileNotFoundException e) {
throw new PidUnavailableException(String.format("PID file (%1$s) could not be found!", pidFile), e);
throw new PidUnavailableException(String.format("PID file [%1$s] not found", pidFile), e);
}
catch (IOException e) {
throw new PidUnavailableException(String.format("Unable to read PID from file (%1$s)!", pidFile), e);
throw new PidUnavailableException(String.format("failed to read PID from file [%1$s]", pidFile), e);
}
catch (NumberFormatException e) {
throw new PidUnavailableException(String.format(
"The value (%1$s) from PID file (%2$s) was not a valid numerical PID!", pidValue, pidFile), e);
"value [%1$s] from PID file [%2$s] was not a valid numerical PID", pidValue, pidFile), e);
}
finally {
IOUtils.close(fileReader);
}
}
public static void writePid(final File pidFile, final int pid) throws IOException {
@SuppressWarnings("all")
public static void writePid(File pidFile, int pid) throws IOException {
Assert.isTrue(pidFile != null && (pidFile.isFile() || pidFile.createNewFile()), String.format(
"The file system pathname (%1$s) in which the PID will be written is not a valid file!", pidFile));
"File [%1$s] is not a valid file", pidFile));
Assert.isTrue(pid > 0, String.format("The PID value (%1$d) must greater than 0!", pid));
Assert.isTrue(pid > 0, String.format("PID [%1$d] must greater than 0", pid));
PrintWriter fileWriter = new PrintWriter(new BufferedWriter(new FileWriter(pidFile, false), 16), true);
@@ -185,7 +187,7 @@ public abstract class ProcessUtils {
}
finally {
pidFile.deleteOnExit();
IOUtils.close(fileWriter);
FileSystemUtils.close(fileWriter);
}
}
@@ -194,8 +196,8 @@ public abstract class ProcessUtils {
protected static final DirectoryPidFileFilter INSTANCE = new DirectoryPidFileFilter();
@Override
public boolean accept(final File pathname) {
return (pathname != null && (pathname.isDirectory() || super.accept(pathname)));
public boolean accept(File path) {
return (path != null && (path.isDirectory() || super.accept(path)));
}
}
@@ -204,8 +206,8 @@ public abstract class ProcessUtils {
protected static final PidFileFilter INSTANCE = new PidFileFilter();
@Override
public boolean accept(final File pathname) {
return (pathname != null && pathname.isFile() && pathname.getName().endsWith(".pid"));
public boolean accept(File path) {
return (path != null && path.isFile() && path.getName().toLowerCase().endsWith(".pid"));
}
}

View File

@@ -42,7 +42,7 @@ import org.springframework.util.Assert;
@SuppressWarnings("unused")
public abstract class AbstractGemFireClientServerIntegrationTest {
protected static long DEFAULT_WAIT_TIME_FOR_SERVER_TO_START = TimeUnit.SECONDS.toMillis(20);
protected static long DEFAULT_TIME_TO_WAIT_FOR_SERVER_TO_START = TimeUnit.SECONDS.toMillis(20);
protected static long FIVE_HUNDRED_MILLISECONDS = TimeUnit.MILLISECONDS.toMillis(500);
protected static long ONE_SECOND_IN_MILLISECONDS = TimeUnit.SECONDS.toMillis(1);
@@ -58,11 +58,11 @@ public abstract class AbstractGemFireClientServerIntegrationTest {
);
}
protected static ProcessWrapper setupGemFireServer(final Class<?> testClass) throws IOException {
return setupGemFireServer(testClass, DEFAULT_WAIT_TIME_FOR_SERVER_TO_START);
protected static ProcessWrapper runGemFireServer(Class<?> testClass) throws IOException {
return runGemFireServer(testClass, DEFAULT_TIME_TO_WAIT_FOR_SERVER_TO_START);
}
protected static ProcessWrapper setupGemFireServer(final Class<?> testClass, final long waitTimeInMilliseconds) throws IOException {
protected static ProcessWrapper runGemFireServer(Class<?> testClass, long waitTimeInMilliseconds) throws IOException {
String serverName = testClass.getSimpleName() + "Server";
File serverWorkingDirectory = new File(FileSystemUtils.WORKING_DIRECTORY, serverName.toLowerCase());
@@ -74,18 +74,18 @@ public abstract class AbstractGemFireClientServerIntegrationTest {
arguments.add(String.format("-Dgemfire.name=%1$s", serverName));
arguments.add("/".concat(testClass.getName().replace(".", "/").concat("-server-context.xml")));
ProcessWrapper serverProcess = ProcessExecutor.launch(serverWorkingDirectory, ServerProcess.class,
ProcessWrapper gemfireServerProcess = ProcessExecutor.launch(serverWorkingDirectory, ServerProcess.class,
arguments.toArray(new String[arguments.size()]));
waitForServerToStart(serverProcess, waitTimeInMilliseconds);
waitForServerToStart(gemfireServerProcess, waitTimeInMilliseconds);
System.out.printf("The Spring-based, GemFire Cache Server process for %1$s should be running...%n",
testClass.getSimpleName());
return serverProcess;
return gemfireServerProcess;
}
static void waitForServerToStart(final ProcessWrapper process, final long duration) {
static void waitForServerToStart(final ProcessWrapper process, long duration) {
ThreadUtils.timedWait(Math.max(duration, FIVE_HUNDRED_MILLISECONDS), FIVE_HUNDRED_MILLISECONDS,
new ThreadUtils.WaitCondition() {
private File processPidControlFile = new File(process.getWorkingDirectory(),
@@ -98,7 +98,7 @@ public abstract class AbstractGemFireClientServerIntegrationTest {
);
}
protected static void tearDownGemFireServer(final ProcessWrapper process) {
protected static void stopGemFireServer(ProcessWrapper process) {
process.shutdown();
if (Boolean.valueOf(System.getProperty(PROCESS_WORKING_DIRECTORY_CLEAN_SYSTEM_PROPERTY, Boolean.TRUE.toString()))) {

View File

@@ -43,21 +43,20 @@ public abstract class FileSystemUtils extends FileUtils {
public static final File USER_HOME = new File(System.getProperty("user.home"));
public static final File WORKING_DIRECTORY = new File(System.getProperty("user.dir"));
public static boolean deleteRecursive(final File path) {
assert path != null;
public static boolean deleteRecursive(File path) {
boolean success = true;
if (path.isDirectory()) {
if (isDirectory(path)) {
for (File file : safeListFiles(path)) {
success &= deleteRecursive(file);
}
}
return (path.delete() && success);
return ((path == null || path.delete()) && success);
}
public static File getRootRelativeToWorkingDirectoryOrPath(final File path) {
// returns sub-directory just below working directory
public static File getRootRelativeToWorkingDirectoryOrPath(File path) {
File localPath = path;
if (isDirectory(localPath)) {
@@ -69,14 +68,14 @@ public abstract class FileSystemUtils extends FileUtils {
return (localPath != null ? localPath : path);
}
public static File[] listFiles(final File directory, final FileFilter fileFilter) {
Assert.isTrue(directory != null && directory.isDirectory(), String.format(
"File (%1$s) does not refer to a valid directory", directory));
public static File[] listFiles(File directory, FileFilter fileFilter) {
Assert.isTrue(isDirectory(directory), String.format( "File (%1$s) does not refer to a valid directory",
directory));
List<File> results = new ArrayList<File>();
for (File file : safeListFiles(directory, fileFilter)) {
if (file.isDirectory()) {
if (isDirectory(file)) {
results.addAll(Arrays.asList(listFiles(file, fileFilter)));
}
else {
@@ -87,12 +86,12 @@ public abstract class FileSystemUtils extends FileUtils {
return results.toArray(new File[results.size()]);
}
public static File[] safeListFiles(final File directory) {
public static File[] safeListFiles(File directory) {
return safeListFiles(directory, AllFiles.INSTANCE);
}
public static File[] safeListFiles(final File directory, final FileFilter fileFilter) {
File[] files = (directory != null ? directory.listFiles(fileFilter) : new File[0]);
public static File[] safeListFiles(File directory, FileFilter fileFilter) {
File[] files = (directory != null ? directory.listFiles(fileFilter) : null);
return (files != null ? files : new File[0]);
}

View File

@@ -49,12 +49,10 @@ public abstract class FileUtils extends IOUtils {
return (path != null && path.isFile());
}
// TODO refactor and perhaps replace with org.springframework.util.FileCopyUtils.copyToString(:Reader)
public static String read(final File file) throws IOException {
Assert.isTrue(file != null && file.isFile(), String.format(
"The File reference (%1$s) from which to read the contents is not a valid file!", file));
assert file != null;
@SuppressWarnings("all")
public static String read(File file) throws IOException {
Assert.isTrue(isFile(file), String.format(
"File [%1$s], from which to read the contents of, does not refer to a valid file", file));
BufferedReader fileReader = new BufferedReader(new FileReader(file));
@@ -73,10 +71,11 @@ public abstract class FileUtils extends IOUtils {
}
}
// TODO refactor and perhaps replace with org.springframework.util.FileCopyUtils.copy(:String, :Writer)
public static void write(final File file, final String contents) throws IOException {
Assert.notNull(file, "The File to write to must not be null!");
Assert.isTrue(StringUtils.hasText(contents), "The 'contents' of the file cannot be null or empty!");
public static void write(File file, String contents) throws IOException {
Assert.notNull(file, "File must not be null!");
Assert.isTrue(StringUtils.hasText(contents), String.format(
"The contents for File [%1$s] cannot be null or empty", file));
BufferedWriter fileWriter = null;

View File

@@ -30,9 +30,9 @@ import java.util.logging.Logger;
@SuppressWarnings("unused")
public abstract class IOUtils {
private static final Logger log = Logger.getLogger(IOUtils.class.getName());
protected static final Logger log = Logger.getLogger(IOUtils.class.getName());
public static boolean close(final Closeable closeable) {
public static boolean close(Closeable closeable) {
if (closeable != null) {
try {
closeable.close();
@@ -40,10 +40,9 @@ public abstract class IOUtils {
}
catch (IOException ignore) {
if (log.isLoggable(Level.FINE)) {
log.fine(String.format("Failed to close Closeable object (%1$s) due to I/O error:%n%2$s",
log.fine(String.format("Failed to close the Closeable object (%1$s) due to an I/O error:%n%2$s",
closeable, ThrowableUtils.toString(ignore)));
}
}
}