From f232ddf894a65db105e8a07ccd7c9718bc72fd98 Mon Sep 17 00:00:00 2001 From: John Blum Date: Wed, 23 May 2018 19:44:00 -0700 Subject: [PATCH] Refactor common integration test logic into the o.s.d.g.tests.integration.IntegrationTestsSupport class. Add utility method to close a o.a.g.cache.GemFireCache instance and wait on the cache closed event. --- .../ClientServerIntegrationTestsSupport.java | 80 ++------------ .../integration/IntegrationTestsSupport.java | 101 ++++++++++++++++++ 2 files changed, 107 insertions(+), 74 deletions(-) create mode 100644 spring-test-data-geode/src/main/java/org/springframework/data/gemfire/tests/integration/IntegrationTestsSupport.java diff --git a/spring-test-data-geode/src/main/java/org/springframework/data/gemfire/tests/integration/ClientServerIntegrationTestsSupport.java b/spring-test-data-geode/src/main/java/org/springframework/data/gemfire/tests/integration/ClientServerIntegrationTestsSupport.java index 4c38036..7f92ae3 100644 --- a/spring-test-data-geode/src/main/java/org/springframework/data/gemfire/tests/integration/ClientServerIntegrationTestsSupport.java +++ b/spring-test-data-geode/src/main/java/org/springframework/data/gemfire/tests/integration/ClientServerIntegrationTestsSupport.java @@ -27,7 +27,6 @@ import java.net.Socket; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; import java.util.Optional; -import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicBoolean; import org.apache.geode.cache.server.CacheServer; @@ -49,49 +48,37 @@ import org.springframework.data.gemfire.util.CollectionUtils; * @see java.net.Socket * @see java.time.LocalDateTime * @see org.apache.geode.cache.server.CacheServer + * @see org.springframework.context.ApplicationContext * @see org.springframework.context.annotation.AnnotationConfigApplicationContext + * @see org.springframework.data.gemfire.tests.integration.IntegrationTestsSupport * @see org.springframework.data.gemfire.tests.process.ProcessExecutor * @see org.springframework.data.gemfire.tests.process.ProcessWrapper - * @see SocketUtils - * @see ThreadUtils * @since 0.0.1 */ @SuppressWarnings("unused") -public class ClientServerIntegrationTestsSupport { - - protected static final long DEFAULT_WAIT_DURATION = TimeUnit.SECONDS.toMillis(30); - protected static final long DEFAULT_WAIT_INTERVAL = 500L; // milliseconds +public abstract class ClientServerIntegrationTestsSupport extends IntegrationTestsSupport { protected static final String DEBUG_ENDPOINT = "-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=5005"; protected static final String DEBUGGING_ENABLED_PROPERTY = "spring.data.gemfire.debugging.enabled"; protected static final String DEFAULT_HOSTNAME = "localhost"; protected static final String DIRECTORY_DELETE_ON_EXIT_PROPERTY = "spring.data.gemfire.directory.delete-on-exit"; protected static final String GEMFIRE_CACHE_SERVER_PORT_PROPERTY = "spring.data.gemfire.cache.server.port"; - protected static final String GEMFIRE_LOG_FILE = "gemfire-server.log"; - protected static final String GEMFIRE_LOG_FILE_PROPERTY = "spring.data.gemfire.log.file"; - protected static final String GEMFIRE_LOG_LEVEL = "warning"; - protected static final String GEMFIRE_LOG_LEVEL_PROPERTY = "spring.data.gemfire.log.level"; protected static final String PROCESS_RUN_MANUAL_PROPERTY = "spring.data.gemfire.process.run-manual"; protected static final String SYSTEM_PROPERTIES_LOG_FILE = "system-properties.log"; - protected static final String TEST_GEMFIRE_LOG_LEVEL = "warning"; - /* (non-Javadoc) */ protected static String asApplicationName(Class type) { return type.getSimpleName(); } - /* (non-Javadoc) */ protected static String asDirectoryName(Class type) { return String.format("%1$s-%2$s", asApplicationName(type), LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd-hh-mm-ss"))); } - /* (non-Javadoc) */ protected static File createDirectory(String pathname) { return createDirectory(new File(pathname)); } - /* (non-Javadoc) */ protected static File createDirectory(File directory) { assertThat(directory.isDirectory() || directory.mkdirs()) @@ -104,7 +91,6 @@ public class ClientServerIntegrationTestsSupport { return directory; } - /* (non-Javadoc) */ protected static int findAvailablePort() throws IOException { ServerSocket serverSocket = null; @@ -118,110 +104,89 @@ public class ClientServerIntegrationTestsSupport { } } - /* (non-Javadoc) */ protected static String getClassNameAsPath(Class type) { return type.getName().replaceAll("\\.", "/"); } - /* (non-Javadoc) */ protected static String getClassNameAsPath(Object obj) { return getClassNameAsPath(obj.getClass()); } - /* (non-Javadoc) */ protected static String getPackageNameAsPath(Class type) { return type.getPackage().getName().replaceAll("\\.", "/"); } - /* (non-Javadoc) */ protected static String getPackageNameAsPath(Object obj) { return getPackageNameAsPath(obj.getClass()); } - /* (non-Javadoc) */ protected static String getContextXmlFileLocation(Class type) { return getClassNameAsPath(type).concat("-context.xml"); } - /* (non-Javadoc) */ protected static String getServerContextXmlFileLocation(Class type) { return getClassNameAsPath(type).concat("-server-context.xml"); } - /* (non-Javadoc) */ protected static boolean isDeleteDirectoryOnExit() { return Boolean.valueOf(System.getProperty(DIRECTORY_DELETE_ON_EXIT_PROPERTY, Boolean.TRUE.toString())); } - /* (non-Javadoc) */ protected static int intValue(Number number) { - return (number != null ? number.intValue() : 0); + return number != null ? number.intValue() : 0; } - /* (non-Javadoc) */ protected static String logFile() { return logFile(GEMFIRE_LOG_FILE); } - /* (non-Javadoc) */ protected static String logFile(String defaultLogFilePathname) { return System.getProperty(GEMFIRE_LOG_FILE_PROPERTY, defaultLogFilePathname); } - /* (non-Javadoc) */ protected static String logLevel() { return logLevel(GEMFIRE_LOG_LEVEL); } - /* (non-Javadoc) */ protected static String logLevel(String defaultLogLevel) { return System.getProperty(GEMFIRE_LOG_LEVEL_PROPERTY, defaultLogLevel); } - /* (non-Javadoc) */ protected static void logSystemProperties() throws IOException { FileUtils.write(new File(SYSTEM_PROPERTIES_LOG_FILE), String.format("%s", CollectionUtils.toString(System.getProperties()))); } - /* (non-Javadoc) */ protected static ProcessWrapper run(Class type, String... arguments) throws IOException { return run(createDirectory(asDirectoryName(type)), type, arguments); } - /* (non-Javadoc) */ protected static ProcessWrapper run(File workingDirectory, Class type, String... arguments) throws IOException { - return (isProcessRunAuto() ? launch(createDirectory(workingDirectory), type, arguments) : null); + return isProcessRunAuto() ? launch(createDirectory(workingDirectory), type, arguments) : null; } - /* (non-Javadoc) */ protected static ProcessWrapper run(String classpath, Class type, String... arguments) throws IOException { return run(createDirectory(asDirectoryName(type)), classpath, type, arguments); } - /* (non-Javadoc) */ protected static ProcessWrapper run(File workingDirectory, String classpath, Class type, String... arguments) throws IOException { - return (isProcessRunAuto() ? launch(createDirectory(workingDirectory), classpath, type, arguments) : null); + return isProcessRunAuto() ? launch(createDirectory(workingDirectory), classpath, type, arguments) : null; } - /* (non-Javadoc) */ protected static boolean isProcessRunAuto() { return !isProcessRunManual(); } - /* (non-Javadoc) */ protected static boolean isProcessRunManual() { return Boolean.getBoolean(PROCESS_RUN_MANUAL_PROPERTY); } - /* (non-Javadoc) */ protected static AnnotationConfigApplicationContext runSpringApplication(Class annotatedClass, String... args) { return runSpringApplication(asArray(annotatedClass), args); } - /* (non-Javadoc) */ protected static AnnotationConfigApplicationContext runSpringApplication(Class[] annotatedClasses, String... args) { @@ -233,12 +198,10 @@ public class ClientServerIntegrationTestsSupport { return applicationContext; } - /* (non-Javadoc) */ protected static boolean stop(ProcessWrapper process) { return stop(process, DEFAULT_WAIT_DURATION); } - /* (non-Javadoc) */ protected static boolean stop(ProcessWrapper process, long duration) { return Optional.ofNullable(process) @@ -255,22 +218,18 @@ public class ClientServerIntegrationTestsSupport { .orElse(true); } - /* (non-Javadoc) */ protected static boolean waitForCacheServerToStart(CacheServer cacheServer) { return waitForServerToStart(cacheServer.getBindAddress(), cacheServer.getPort(), DEFAULT_WAIT_DURATION); } - /* (non-Javadoc) */ protected static boolean waitForCacheServerToStart(CacheServer cacheServer, long duration) { return waitForServerToStart(cacheServer.getBindAddress(), cacheServer.getPort(), duration); } - /* (non-Javadoc) */ protected static boolean waitForServerToStart(String host, int port) { return waitForServerToStart(host, port, DEFAULT_WAIT_DURATION); } - /* (non-Javadoc) */ protected static boolean waitForServerToStart(final String host, final int port, long duration) { return ThreadUtils.timedWait(duration, DEFAULT_WAIT_INTERVAL, new ThreadUtils.WaitCondition() { @@ -297,31 +256,4 @@ public class ClientServerIntegrationTestsSupport { } }); } - - protected static boolean waitOn(Condition condition) { - return waitOn(condition, DEFAULT_WAIT_DURATION); - } - - @SuppressWarnings("all") - protected static boolean waitOn(Condition condition, long duration) { - - long timeout = (System.currentTimeMillis() + duration); - - try { - while (!condition.evaluate() && System.currentTimeMillis() < timeout) { - synchronized (condition) { - TimeUnit.MILLISECONDS.timedWait(condition, DEFAULT_WAIT_INTERVAL); - } - } - } - catch (InterruptedException e) { - Thread.currentThread().interrupt(); - } - - return condition.evaluate(); - } - - protected interface Condition { - boolean evaluate(); - } } diff --git a/spring-test-data-geode/src/main/java/org/springframework/data/gemfire/tests/integration/IntegrationTestsSupport.java b/spring-test-data-geode/src/main/java/org/springframework/data/gemfire/tests/integration/IntegrationTestsSupport.java new file mode 100644 index 0000000..5daa7ef --- /dev/null +++ b/spring-test-data-geode/src/main/java/org/springframework/data/gemfire/tests/integration/IntegrationTestsSupport.java @@ -0,0 +1,101 @@ +/* + * Copyright 2018 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.tests.integration; + +import java.util.Optional; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicBoolean; + +import org.apache.geode.cache.CacheClosedException; +import org.apache.geode.cache.GemFireCache; +import org.springframework.data.gemfire.GemfireUtils; + +/** + * The IntegrationTestsSupport class... + * + * @author John Blum + * @since 1.0.0 + */ +@SuppressWarnings("unused") +public abstract class IntegrationTestsSupport { + + protected static final long DEFAULT_WAIT_DURATION = TimeUnit.SECONDS.toMillis(30); + protected static final long DEFAULT_WAIT_INTERVAL = 500L; // milliseconds + + protected static final String GEMFIRE_LOG_FILE = "gemfire-server.log"; + protected static final String GEMFIRE_LOG_FILE_PROPERTY = "spring.data.gemfire.log.file"; + protected static final String GEMFIRE_LOG_LEVEL = "warning"; + protected static final String GEMFIRE_LOG_LEVEL_PROPERTY = "spring.data.gemfire.log.level"; + protected static final String TEST_GEMFIRE_LOG_LEVEL = "warning"; + + public static void closeGemFireCacheWaitOnCloseEvent() { + closeGemFireCacheWaitOnCloseEvent(DEFAULT_WAIT_DURATION); + } + + public static void closeGemFireCacheWaitOnCloseEvent(long duration) { + + AtomicBoolean closed = new AtomicBoolean(false); + + waitOn(() -> { + try { + return Optional.ofNullable(GemfireUtils.resolveGemFireCache()) + .filter(cache -> !closed.get()) + .filter(cache -> !cache.isClosed()) + .map(IntegrationTestsSupport::close) + .map(GemFireCache::isClosed) + .orElse(true); + } + catch (CacheClosedException ignore) { + closed.set(true); + return true; + } + }, duration); + } + + private static GemFireCache close(GemFireCache cache) { + cache.close(); + return cache; + } + + protected static boolean waitOn(Condition condition) { + return waitOn(condition, DEFAULT_WAIT_DURATION); + } + + @SuppressWarnings("all") + protected static boolean waitOn(Condition condition, long duration) { + + long timeout = System.currentTimeMillis() + duration; + + try { + while (!condition.evaluate() && System.currentTimeMillis() < timeout) { + synchronized (condition) { + TimeUnit.MILLISECONDS.timedWait(condition, DEFAULT_WAIT_INTERVAL); + } + } + } + catch (InterruptedException cause) { + Thread.currentThread().interrupt(); + } + + return condition.evaluate(); + } + + @FunctionalInterface + protected interface Condition { + boolean evaluate(); + } +}