docs.AbstractGemFireIntegrationTests.java Source code

Java tutorial

Introduction

Here is the source code for docs.AbstractGemFireIntegrationTests.java

Source

/*
 * Copyright 2014-2016 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 docs;

import java.io.File;
import java.io.IOException;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;

import com.gemstone.gemfire.cache.Cache;
import com.gemstone.gemfire.cache.CacheClosedException;
import com.gemstone.gemfire.cache.DataPolicy;
import com.gemstone.gemfire.cache.ExpirationAction;
import com.gemstone.gemfire.cache.ExpirationAttributes;
import com.gemstone.gemfire.cache.GemFireCache;
import com.gemstone.gemfire.cache.Region;
import com.gemstone.gemfire.cache.client.ClientCache;
import com.gemstone.gemfire.cache.client.ClientCacheFactory;
import com.gemstone.gemfire.cache.query.Index;
import com.gemstone.gemfire.cache.server.CacheServer;
import org.junit.Before;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationListener;
import org.springframework.session.ExpiringSession;
import org.springframework.session.data.gemfire.GemFireOperationsSessionRepository;
import org.springframework.session.data.gemfire.support.GemFireUtils;
import org.springframework.session.events.AbstractSessionEvent;

import static org.assertj.core.api.Assertions.assertThat;

/**
 * AbstractGemFireIntegrationTests is an abstract base class encapsulating common
 * operations for writing Spring Session GemFire integration tests.
 *
 * @author John Blum
 * @since 1.1.0
 * @see org.springframework.session.ExpiringSession
 * @see org.springframework.session.events.AbstractSessionEvent
 * @see com.gemstone.gemfire.cache.Cache
 * @see com.gemstone.gemfire.cache.DataPolicy
 * @see com.gemstone.gemfire.cache.ExpirationAttributes
 * @see com.gemstone.gemfire.cache.GemFireCache
 * @see com.gemstone.gemfire.cache.Region
 * @see com.gemstone.gemfire.cache.client.ClientCache
 * @see com.gemstone.gemfire.cache.server.CacheServer
 */
public class AbstractGemFireIntegrationTests {
    public static final String GEMFIRE_LOG_LEVEL = System.getProperty("spring.session.data.gemfire.log-level",
            "warning");

    protected static final boolean DEFAULT_ENABLE_QUERY_DEBUGGING = false;
    protected static final boolean GEMFIRE_QUERY_DEBUG = Boolean
            .getBoolean("spring.session.data.gemfire.query.debug");

    protected static final int DEFAULT_GEMFIRE_SERVER_PORT = CacheServer.DEFAULT_PORT;

    protected static final long DEFAULT_WAIT_DURATION = TimeUnit.SECONDS.toMillis(20);
    protected static final long DEFAULT_WAIT_INTERVAL = 500L;

    protected static final File WORKING_DIRECTORY = new File(System.getProperty("user.dir"));

    protected static final String DEFAULT_PROCESS_CONTROL_FILENAME = "process.ctl";

    protected static final String GEMFIRE_LOG_FILE_NAME = System.getProperty("spring.session.data.gemfire.log-file",
            "server.log");

    @Autowired
    protected Cache gemfireCache;

    @Autowired
    protected GemFireOperationsSessionRepository sessionRepository;

    @Before
    public void setup() {
        System.setProperty("gemfire.Query.VERBOSE", String.valueOf(isQueryDebuggingEnabled()));
    }

    /* (non-Javadoc) */
    protected static File createDirectory(String pathname) {
        File directory = new File(WORKING_DIRECTORY, pathname);

        assertThat(directory.isDirectory() || directory.mkdirs())
                .as(String.format("Failed to create directory (%1$s)", directory)).isTrue();

        directory.deleteOnExit();

        return directory;
    }

    /* (non-Javadoc) */
    protected static List<String> createJavaProcessCommandLine(Class<?> type, String... args) {
        List<String> commandLine = new ArrayList<String>();

        String javaHome = System.getProperty("java.home");
        String javaExe = new File(new File(javaHome, "bin"), "java").getAbsolutePath();

        commandLine.add(javaExe);
        commandLine.add("-server");
        commandLine.add("-ea");
        commandLine.add(String.format("-Dgemfire.log-file=%1$s", GEMFIRE_LOG_FILE_NAME));
        commandLine.add(String.format("-Dgemfire.log-level=%1$s", GEMFIRE_LOG_LEVEL));
        commandLine.add(String.format("-Dgemfire.Query.VERBOSE=%1$s", GEMFIRE_QUERY_DEBUG));
        commandLine.addAll(extractJvmArguments(args));
        commandLine.add("-classpath");
        commandLine.add(System.getProperty("java.class.path"));
        commandLine.add(type.getName());
        commandLine.addAll(extractProgramArguments(args));

        // System.err.printf("Java process command-line is (%1$s)%n", commandLine);

        return commandLine;
    }

    /* (non-Javadoc) */
    protected static List<String> extractJvmArguments(final String... args) {
        List<String> jvmArgs = new ArrayList<String>(args.length);

        for (String arg : args) {
            if (arg.startsWith("-")) {
                jvmArgs.add(arg);
            }
        }

        return jvmArgs;
    }

    /* (non-Javadoc) */
    protected static List<String> extractProgramArguments(final String... args) {
        List<String> jvmArgs = new ArrayList<String>(args.length);

        for (String arg : args) {
            if (!arg.startsWith("-")) {
                jvmArgs.add(arg);
            }
        }

        return jvmArgs;
    }

    /* (non-Javadoc) */
    protected static Process run(Class<?> type, File directory, String... args) throws IOException {
        return new ProcessBuilder().command(createJavaProcessCommandLine(type, args)).directory(directory).start();
    }

    /* (non-Javadoc) */
    protected static boolean waitForCacheServerToStart(CacheServer cacheServer) {
        return waitForCacheServerToStart(cacheServer, DEFAULT_WAIT_DURATION);
    }

    /* (non-Javadoc) */
    protected static boolean waitForCacheServerToStart(CacheServer cacheServer, long duration) {
        return waitForCacheServerToStart(cacheServer.getBindAddress(), cacheServer.getPort(), duration);
    }

    /* (non-Javadoc) */
    protected static boolean waitForCacheServerToStart(String host, int port) {
        return waitForCacheServerToStart(host, port, DEFAULT_WAIT_DURATION);
    }

    /* (non-Javadoc) */
    protected static boolean waitForCacheServerToStart(final String host, final int port, long duration) {
        return waitOnCondition(new Condition() {
            AtomicBoolean connected = new AtomicBoolean(false);

            public boolean evaluate() {
                Socket socket = null;

                try {
                    if (!connected.get()) {
                        socket = new Socket(host, port);
                        connected.set(true);
                    }
                } catch (IOException ignore) {
                } finally {
                    GemFireUtils.close(socket);
                }

                return connected.get();
            }
        }, duration);
    }

    // NOTE this method would not be necessary except Spring Sessions' build does not fork
    // the test JVM
    // for every test class.
    /* (non-Javadoc) */
    protected static boolean waitForClientCacheToClose() {
        return waitForClientCacheToClose(DEFAULT_WAIT_DURATION);
    }

    /* (non-Javadoc) */
    protected static boolean waitForClientCacheToClose(long duration) {
        try {
            final ClientCache clientCache = ClientCacheFactory.getAnyInstance();

            clientCache.close();

            waitOnCondition(new Condition() {
                public boolean evaluate() {
                    return clientCache.isClosed();
                }
            }, duration);

            return clientCache.isClosed();
        } catch (CacheClosedException ignore) {
            return true;
        }

    }

    /* (non-Javadoc) */
    protected static boolean waitForProcessToStart(Process process, File directory) {
        return waitForProcessToStart(process, directory, DEFAULT_WAIT_DURATION);
    }

    /* (non-Javadoc) */
    @SuppressWarnings("all")
    protected static boolean waitForProcessToStart(Process process, File directory, long duration) {
        final File processControl = new File(directory, DEFAULT_PROCESS_CONTROL_FILENAME);

        waitOnCondition(new Condition() {
            public boolean evaluate() {
                return processControl.isFile();
            }
        }, duration);

        return process.isAlive();
    }

    /* (non-Javadoc) */
    protected static int waitForProcessToStop(Process process, File directory) {
        return waitForProcessToStop(process, directory, DEFAULT_WAIT_DURATION);
    }

    /* (non-Javadoc) */
    protected static int waitForProcessToStop(Process process, File directory, long duration) {
        final long timeout = (System.currentTimeMillis() + duration);

        try {
            while (process.isAlive() && System.currentTimeMillis() < timeout) {
                if (process.waitFor(DEFAULT_WAIT_INTERVAL, TimeUnit.MILLISECONDS)) {
                    return process.exitValue();
                }
            }
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }

        return (process.isAlive() ? -1 : process.exitValue());
    }

    /* (non-Javadoc) */
    protected static boolean waitOnCondition(Condition condition) {
        return waitOnCondition(condition, DEFAULT_WAIT_DURATION);
    }

    /* (non-Javadoc) */
    @SuppressWarnings("all")
    protected static boolean waitOnCondition(Condition condition, long duration) {
        final 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();
    }

    /* (non-Javadoc) */
    protected static File writeProcessControlFile(File path) throws IOException {
        assertThat(path != null && path.isDirectory()).isTrue();

        File processControl = new File(path, DEFAULT_PROCESS_CONTROL_FILENAME);

        assertThat(processControl.createNewFile()).isTrue();

        processControl.deleteOnExit();

        return processControl;
    }

    /* (non-Javadoc) */
    protected void assertRegion(Region<?, ?> actualRegion, String expectedName, DataPolicy expectedDataPolicy) {
        assertThat(actualRegion).isNotNull();
        assertThat(actualRegion.getName()).isEqualTo(expectedName);
        assertThat(actualRegion.getFullPath()).isEqualTo(GemFireUtils.toRegionPath(expectedName));
        assertThat(actualRegion.getAttributes()).isNotNull();
        assertThat(actualRegion.getAttributes().getDataPolicy()).isEqualTo(expectedDataPolicy);
    }

    /* (non-Javadoc) */
    protected void assertIndex(Index index, String expectedExpression, String expectedFromClause) {
        assertThat(index).isNotNull();
        assertThat(index.getIndexedExpression()).isEqualTo(expectedExpression);
        assertThat(index.getFromClause()).isEqualTo(expectedFromClause);
    }

    /* (non-Javadoc) */
    protected void assertEntryIdleTimeout(Region<?, ?> region, ExpirationAction expectedAction,
            int expectedTimeout) {
        assertEntryIdleTimeout(region.getAttributes().getEntryIdleTimeout(), expectedAction, expectedTimeout);
    }

    /* (non-Javadoc) */
    protected void assertEntryIdleTimeout(ExpirationAttributes actualExpirationAttributes,
            ExpirationAction expectedAction, int expectedTimeout) {
        assertThat(actualExpirationAttributes).isNotNull();
        assertThat(actualExpirationAttributes.getAction()).isEqualTo(expectedAction);
        assertThat(actualExpirationAttributes.getTimeout()).isEqualTo(expectedTimeout);
    }

    /* (non-Javadoc) */
    protected boolean enableQueryDebugging() {
        return DEFAULT_ENABLE_QUERY_DEBUGGING;
    }

    /* (non-Javadoc) */
    protected boolean isQueryDebuggingEnabled() {
        return (GEMFIRE_QUERY_DEBUG || enableQueryDebugging());
    }

    /* (non-Javadoc) */
    protected List<String> listRegions(GemFireCache gemfireCache) {
        Set<Region<?, ?>> regions = gemfireCache.rootRegions();

        List<String> regionList = new ArrayList<String>(regions.size());

        for (Region<?, ?> region : regions) {
            regionList.add(region.getFullPath());
        }

        return regionList;
    }

    /* (non-Javadoc) */
    @SuppressWarnings("unchecked")
    protected <T extends ExpiringSession> T createSession() {
        T expiringSession = (T) this.sessionRepository.createSession();
        assertThat(expiringSession).isNotNull();
        return expiringSession;
    }

    /* (non-Javadoc) */
    @SuppressWarnings("unchecked")
    protected <T extends ExpiringSession> T createSession(String principalName) {
        GemFireOperationsSessionRepository.GemFireSession session = createSession();
        session.setPrincipalName(principalName);
        return (T) session;
    }

    /* (non-Javadoc) */
    protected <T extends ExpiringSession> T expire(T session) {
        session.setLastAccessedTime(0L);
        return session;
    }

    /* (non-Javadoc) */
    @SuppressWarnings("unchecked")
    protected <T extends ExpiringSession> T get(String sessionId) {
        return (T) this.sessionRepository.getSession(sessionId);
    }

    /* (non-Javadoc) */
    protected <T extends ExpiringSession> T save(T session) {
        this.sessionRepository.save(session);
        return session;
    }

    /* (non-Javadoc) */
    protected <T extends ExpiringSession> T touch(T session) {
        session.setLastAccessedTime(System.currentTimeMillis());
        return session;
    }

    /**
     * The SessionEventListener class is a Spring {@link ApplicationListener} listening
     * for Spring HTTP Session application events.
     *
     * @see org.springframework.context.ApplicationListener
     * @see org.springframework.session.events.AbstractSessionEvent
     */
    public static class SessionEventListener implements ApplicationListener<AbstractSessionEvent> {

        private volatile AbstractSessionEvent sessionEvent;

        /* (non-Javadoc) */
        @SuppressWarnings("unchecked")
        public <T extends AbstractSessionEvent> T getSessionEvent() {
            T sessionEvent = (T) this.sessionEvent;
            this.sessionEvent = null;
            return sessionEvent;
        }

        /* (non-Javadoc) */
        public void onApplicationEvent(AbstractSessionEvent event) {
            this.sessionEvent = event;
        }

        /* (non-Javadoc) */
        public <T extends AbstractSessionEvent> T waitForSessionEvent(long duration) {
            waitOnCondition(new Condition() {
                public boolean evaluate() {
                    return (SessionEventListener.this.sessionEvent != null);
                }
            }, duration);

            return getSessionEvent();
        }
    }

    /**
     * The Condition interface defines a logical condition that must be satisfied before
     * it is safe to proceed.
     */
    protected interface Condition {
        boolean evaluate();
    }

}