From c9639389549b2708c6aa6e843bf4c7836505d490 Mon Sep 17 00:00:00 2001 From: John Blum Date: Tue, 23 Oct 2018 23:02:07 -0700 Subject: [PATCH] Add Integration Test asserting lazy expiration timeouts on Session access using FixedDurationExpirationSessionRepository. Resolves gh-5. --- .../AbstractGemFireIntegrationTests.java | 29 ++++-- ...eoutSessionExpirationIntegrationTests.java | 97 +++++++++++++++++++ 2 files changed, 119 insertions(+), 7 deletions(-) create mode 100644 spring-session-data-geode/src/integration-test/java/org/springframework/session/data/gemfire/expiration/LazyTimeoutSessionExpirationIntegrationTests.java diff --git a/spring-session-data-geode/src/integration-test/java/org/springframework/session/data/gemfire/AbstractGemFireIntegrationTests.java b/spring-session-data-geode/src/integration-test/java/org/springframework/session/data/gemfire/AbstractGemFireIntegrationTests.java index 72bf221..8623ece 100644 --- a/spring-session-data-geode/src/integration-test/java/org/springframework/session/data/gemfire/AbstractGemFireIntegrationTests.java +++ b/spring-session-data-geode/src/integration-test/java/org/springframework/session/data/gemfire/AbstractGemFireIntegrationTests.java @@ -51,6 +51,7 @@ import org.apache.geode.internal.InternalDataSerializer; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ApplicationListener; import org.springframework.session.Session; +import org.springframework.session.SessionRepository; import org.springframework.session.data.gemfire.support.GemFireUtils; import org.springframework.session.events.AbstractSessionEvent; import org.springframework.util.StringUtils; @@ -100,9 +101,16 @@ public abstract class AbstractGemFireIntegrationTests { @Autowired(required = false) protected GemFireOperationsSessionRepository gemfireSessionRepository; + @Autowired(required = false) + protected SessionRepository sessionRepository; + @Before public void setup() { + System.setProperty("gemfire.Query.VERBOSE", String.valueOf(isQueryDebuggingEnabled())); + + this.sessionRepository = this.sessionRepository != null + ? this.sessionRepository : this.gemfireSessionRepository; } protected static String buildClassPathContainingJarFiles(String... jarFilenames) { @@ -125,7 +133,7 @@ public abstract class AbstractGemFireIntegrationTests { private static Optional findClassInFileSystem(Class type) { return Optional.ofNullable(type) - .map(AbstractGemFireIntegrationTests::getResourceName) + .map(AbstractGemFireIntegrationTests::toResourceName) .map(resourceName -> type.getClassLoader().getResource(resourceName)); } @@ -134,7 +142,7 @@ public abstract class AbstractGemFireIntegrationTests { .filter(element -> element.contains(jarFilename)).findFirst(); } - private static String getResourceName(Class type) { + private static String toResourceName(Class type) { return type.getName().replaceAll("\\.", "/").concat(".class"); } @@ -204,7 +212,7 @@ public abstract class AbstractGemFireIntegrationTests { .map(File::getAbsolutePath) .map(pathname -> { - int indexOfTypeName = pathname.indexOf(getResourceName(type)); + int indexOfTypeName = pathname.indexOf(toResourceName(type)); pathname = (indexOfTypeName > -1 ? pathname.substring(0, indexOfTypeName) : pathname); pathname = (pathname.endsWith(File.separator) ? pathname.substring(0, pathname.length() - 1) : pathname); @@ -375,12 +383,14 @@ public abstract class AbstractGemFireIntegrationTests { } protected void assertValidSession(Session session) { + assertThat(session).isNotNull(); assertThat(session.getId()).isNotEmpty(); assertThat(session.isExpired()).isFalse(); } protected void assertRegion(Region actualRegion, String expectedName, DataPolicy expectedDataPolicy) { + assertThat(actualRegion).isNotNull(); assertThat(actualRegion.getName()).isEqualTo(expectedName); assertThat(actualRegion.getFullPath()).isEqualTo(GemFireUtils.toRegionPath(expectedName)); @@ -389,6 +399,7 @@ public abstract class AbstractGemFireIntegrationTests { } protected void assertIndex(Index index, String expectedExpression, String expectedFromClause) { + assertThat(index).isNotNull(); assertThat(index.getIndexedExpression()).isEqualTo(expectedExpression); assertThat(index.getFromClause()).isEqualTo(expectedFromClause); @@ -418,10 +429,14 @@ public abstract class AbstractGemFireIntegrationTests { return gemfireCache.rootRegions().stream().map(Region::getFullPath).collect(Collectors.toList()); } + protected SessionRepository getSessionRepository() { + return this.sessionRepository; + } + @SuppressWarnings("unchecked") protected T createSession() { - T session = (T) this.gemfireSessionRepository.createSession(); + T session = (T) getSessionRepository().createSession(); assertThat(session).isNotNull(); @@ -440,7 +455,7 @@ public abstract class AbstractGemFireIntegrationTests { @SuppressWarnings("all") protected T delete(T session) { - this.gemfireSessionRepository.delete(session); + getSessionRepository().deleteById(session.getId()); return session; } @@ -451,11 +466,11 @@ public abstract class AbstractGemFireIntegrationTests { @SuppressWarnings("unchecked") protected T get(String sessionId) { - return (T) this.gemfireSessionRepository.findById(sessionId); + return (T) getSessionRepository().findById(sessionId); } protected T save(T session) { - this.gemfireSessionRepository.save(session); + getSessionRepository().save(session); return session; } diff --git a/spring-session-data-geode/src/integration-test/java/org/springframework/session/data/gemfire/expiration/LazyTimeoutSessionExpirationIntegrationTests.java b/spring-session-data-geode/src/integration-test/java/org/springframework/session/data/gemfire/expiration/LazyTimeoutSessionExpirationIntegrationTests.java new file mode 100644 index 0000000..687d5e3 --- /dev/null +++ b/spring-session-data-geode/src/integration-test/java/org/springframework/session/data/gemfire/expiration/LazyTimeoutSessionExpirationIntegrationTests.java @@ -0,0 +1,97 @@ +/* + * Copyright 2017 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.session.data.gemfire.expiration; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.time.Duration; + +import org.junit.Test; +import org.junit.runner.RunWith; + +import org.springframework.context.annotation.Bean; +import org.springframework.data.gemfire.config.annotation.PeerCacheApplication; +import org.springframework.data.gemfire.tests.mock.annotation.EnableGemFireMockObjects; +import org.springframework.session.Session; +import org.springframework.session.data.gemfire.AbstractGemFireIntegrationTests; +import org.springframework.session.data.gemfire.config.annotation.web.http.EnableGemFireHttpSession; +import org.springframework.session.data.gemfire.expiration.config.FixedDurationExpirationSessionRepositoryBeanPostProcessor; +import org.springframework.session.data.gemfire.expiration.repository.FixedDurationExpirationSessionRepository; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringRunner; + +/** + * Integration tests asserting lazy expiration timeouts on {@link Session} access + * using {@link FixedDurationExpirationSessionRepository}. + * + * @author John Blum + * @see org.junit.Test + * @see org.springframework.context.annotation.Bean + * @see org.springframework.data.gemfire.config.annotation.ClientCacheApplication + * @see org.springframework.data.gemfire.tests.mock.annotation.EnableGemFireMockObjects + * @see org.springframework.session.data.gemfire.AbstractGemFireIntegrationTests + * @see org.springframework.session.data.gemfire.config.annotation.web.http.EnableGemFireHttpSession + * @see org.springframework.session.data.gemfire.expiration.config.FixedDurationExpirationSessionRepositoryBeanPostProcessor + * @see org.springframework.session.data.gemfire.expiration.repository.FixedDurationExpirationSessionRepository + * @see org.springframework.test.context.ContextConfiguration + * @see org.springframework.test.context.junit4.SpringRunner + * @since 2.1.0 + */ +@RunWith(SpringRunner.class) +@ContextConfiguration +@SuppressWarnings("unused") +public class LazyTimeoutSessionExpirationIntegrationTests extends AbstractGemFireIntegrationTests { + + @Test + public void sessionRepositoryIsAFixedDurationExpirationSessionRepository() { + assertThat(getSessionRepository()).isInstanceOf(FixedDurationExpirationSessionRepository.class); + } + + @Test + public void sessionsExpiresAfterFixedDurationOnLazyAccess() { + + Session session = save(touch(createSession())); + + assertThat(session).isNotNull(); + assertThat(session.getId()).isNotEmpty(); + assertThat(session.isExpired()).isFalse(); + + waitOnCondition(() -> false, Duration.ofSeconds(1).toMillis()); + + Session loadedSession = get(session.getId()); + + assertThat(loadedSession).isEqualTo(session); + assertThat(loadedSession.isExpired()).isFalse(); + + waitOnCondition(() -> false, Duration.ofSeconds(1).toMillis() + 1); + + Session expiredSession = get(loadedSession.getId()); + + assertThat(expiredSession).isNull(); + } + + @PeerCacheApplication + @EnableGemFireHttpSession + @EnableGemFireMockObjects + static class TestConfiguration { + + @Bean + FixedDurationExpirationSessionRepositoryBeanPostProcessor fixedDurationExpirationBeanPostProcessor() { + return new FixedDurationExpirationSessionRepositoryBeanPostProcessor(Duration.ofSeconds(2)); + } + } +}