Add GemFire Support

Fixes GH PR #148 and PR #308 implementing a GemFire Adapter to support
clustered HttpSessions in Spring Session.

* Resolve SGF-373 - Implement a Spring Session Adapter for GemFire backing
a HttpSession similar to the Redis support.
* Add Spring Session annotation to enable GemFire support with
@EnableGemFireHttpSession.
* Add extesion of SpringHttpSessionConfiguration to configure GemFire using
GemFireHttpSessionConfiguration.
* Add implementation of SessionRepository to access clustered, replicated
HttpSession state in GemFire with GemFireOperationsSessionRepository.
* Utilize GemFire Data Serialization framework to both replicate
HttpSession state information as well as handle deltas.
* Utilize GemFire OQL query to lookup arbitrary Session attributes by name,
and in particular the user authenticated principal name.
* Implment unit and integration tests, and in particular, tests for both
peer-to-peer (p2p) and client/server topologies.
* Set initial Spring Data GemFire version to 1.7.2.RELEASE, which depends
on Pivotal GemFire 8.1.0.
* Add documentation, Javadoc and samples along with additional Integration
Tests.

Fixes gh-148
This commit is contained in:
John Blum
2016-01-28 13:19:18 -06:00
committed by Rob Winch
parent 1931da83a5
commit 019e0083b0
68 changed files with 8634 additions and 2 deletions

View File

@@ -0,0 +1,368 @@
/*
* Copyright 2002-2015 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;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyString;
import static org.mockito.Matchers.eq;
import static org.mockito.Matchers.isA;
import static org.mockito.Matchers.same;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import static org.springframework.session.data.gemfire.GemFireOperationsSessionRepository.GemFireSession;
import java.util.Arrays;
import java.util.Collections;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.runners.MockitoJUnitRunner;
import org.mockito.stubbing.Answer;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.data.gemfire.GemfireAccessor;
import org.springframework.data.gemfire.GemfireOperations;
import org.springframework.session.ExpiringSession;
import org.springframework.session.events.AbstractSessionEvent;
import org.springframework.session.events.SessionDeletedEvent;
import com.gemstone.gemfire.cache.AttributesMutator;
import com.gemstone.gemfire.cache.Region;
import com.gemstone.gemfire.cache.query.SelectResults;
/**
* The GemFireOperationsSessionRepositoryTest class is a test suite of test cases testing the contract and functionality
* of the GemFireOperationsSessionRepository class.
*
* @author John Blum
* @see org.junit.Test
* @see org.junit.runner.RunWith
* @see org.mockito.Mock
* @see org.mockito.Mockito
* @see org.mockito.runners.MockitoJUnitRunner
* @see org.springframework.session.data.gemfire.GemFireOperationsSessionRepository
* @since 1.0.0
*/
@RunWith(MockitoJUnitRunner.class)
public class GemFireOperationsSessionRepositoryTest {
protected static final int MAX_INACTIVE_INTERVAL_IN_SECONDS = 600;
@Mock
private ApplicationEventPublisher mockApplicationEventPublisher;
@Mock
private AttributesMutator<Object, ExpiringSession> mockAttributesMutator;
@Mock
private Region<Object, ExpiringSession> mockRegion;
@Mock
private GemfireOperationsAccessor mockTemplate;
private GemFireOperationsSessionRepository sessionRepository;
@Before
public void setup() throws Exception {
when(mockRegion.getAttributesMutator()).thenReturn(mockAttributesMutator);
when(mockRegion.getFullPath()).thenReturn("/Example");
when(mockTemplate.<Object, ExpiringSession>getRegion()).thenReturn(mockRegion);
sessionRepository = new GemFireOperationsSessionRepository(mockTemplate);
sessionRepository.setApplicationEventPublisher(mockApplicationEventPublisher);
sessionRepository.setMaxInactiveIntervalInSeconds(MAX_INACTIVE_INTERVAL_IN_SECONDS);
sessionRepository.afterPropertiesSet();
assertThat(sessionRepository.getApplicationEventPublisher()).isSameAs(mockApplicationEventPublisher);
assertThat(sessionRepository.getFullyQualifiedRegionName()).isEqualTo("/Example");
assertThat(sessionRepository.getMaxInactiveIntervalInSeconds()).isEqualTo(MAX_INACTIVE_INTERVAL_IN_SECONDS);
}
@After
public void tearDown() {
verify(mockAttributesMutator, times(1)).addCacheListener(same(sessionRepository));
verify(mockRegion, times(1)).getFullPath();
verify(mockTemplate, times(1)).getRegion();
}
@Test
@SuppressWarnings("unchecked")
public void findByPrincipalNameFindsMatchingSessions() throws Exception {
ExpiringSession mockSessionOne = mock(ExpiringSession.class, "MockSessionOne");
ExpiringSession mockSessionTwo = mock(ExpiringSession.class, "MockSessionTwo");
ExpiringSession mockSessionThree = mock(ExpiringSession.class, "MockSessionThree");
when(mockSessionOne.getId()).thenReturn("1");
when(mockSessionTwo.getId()).thenReturn("2");
when(mockSessionThree.getId()).thenReturn("3");
SelectResults mockSelectResults = mock(SelectResults.class);
when(mockSelectResults.asList()).thenReturn(Arrays.asList(mockSessionOne, mockSessionTwo, mockSessionThree));
String principalName = "jblum";
String expectedOql = String.format(GemFireOperationsSessionRepository.FIND_SESSIONS_BY_PRINCIPAL_NAME_QUERY,
sessionRepository.getFullyQualifiedRegionName());
when(mockTemplate.find(eq(expectedOql), eq(principalName))).thenReturn(mockSelectResults);
Map<String, ExpiringSession> sessions = sessionRepository.findByPrincipalName(principalName);
assertThat(sessions).isNotNull();
assertThat(sessions.size()).isEqualTo(3);
assertThat(sessions.get("1")).isEqualTo(mockSessionOne);
assertThat(sessions.get("2")).isEqualTo(mockSessionTwo);
assertThat(sessions.get("3")).isEqualTo(mockSessionThree);
verify(mockTemplate, times(1)).find(eq(expectedOql), eq(principalName));
verify(mockSelectResults, times(1)).asList();
verify(mockSessionOne, times(1)).getId();
verify(mockSessionTwo, times(1)).getId();
verify(mockSessionThree, times(1)).getId();
}
@Test
@SuppressWarnings("unchecked")
public void findByPrincipalNameReturnsNoMatchingSessions() {
SelectResults mockSelectResults = mock(SelectResults.class);
when(mockSelectResults.asList()).thenReturn(Collections.emptyList());
String principalName = "jblum";
String expectedOql = String.format(GemFireOperationsSessionRepository.FIND_SESSIONS_BY_PRINCIPAL_NAME_QUERY,
sessionRepository.getFullyQualifiedRegionName());
when(mockTemplate.find(eq(expectedOql), eq(principalName))).thenReturn(mockSelectResults);
Map<String, ExpiringSession> sessions = sessionRepository.findByPrincipalName(principalName);
assertThat(sessions).isNotNull();
assertThat(sessions.isEmpty()).isTrue();
verify(mockTemplate, times(1)).find(eq(expectedOql), eq(principalName));
verify(mockSelectResults, times(1)).asList();
}
@Test
public void createProperlyInitializedSession() {
final long beforeOrAtCreationTime = System.currentTimeMillis();
ExpiringSession session = sessionRepository.createSession();
assertThat(session).isInstanceOf(GemFireSession.class);
assertThat(session.getId()).isNotNull();
assertThat(session.getAttributeNames().isEmpty()).isTrue();
assertThat(session.getCreationTime()).isGreaterThanOrEqualTo(beforeOrAtCreationTime);
assertThat(session.getLastAccessedTime()).isGreaterThanOrEqualTo(beforeOrAtCreationTime);
assertThat(session.getMaxInactiveIntervalInSeconds()).isEqualTo(MAX_INACTIVE_INTERVAL_IN_SECONDS);
}
@Test
public void getSessionDeletesMatchingExpiredSessionById() {
final String expectedSessionId = "1";
final ExpiringSession mockSession = mock(ExpiringSession.class);
when(mockSession.isExpired()).thenReturn(true);
when(mockSession.getId()).thenReturn(expectedSessionId);
when(mockTemplate.get(eq(expectedSessionId))).thenReturn(mockSession);
when(mockTemplate.remove(eq(expectedSessionId))).thenReturn(mockSession);
doAnswer(new Answer<Void>() {
public Void answer(final InvocationOnMock invocation) throws Throwable {
ApplicationEvent applicationEvent = invocation.getArgumentAt(0, ApplicationEvent.class);
assertThat(applicationEvent).isInstanceOf(SessionDeletedEvent.class);
AbstractSessionEvent sessionEvent = (AbstractSessionEvent) applicationEvent;
assertThat(sessionEvent.getSource()).isSameAs(sessionRepository);
assertThat(sessionEvent.getSession()).isSameAs(mockSession);
assertThat(sessionEvent.getSessionId()).isEqualTo(expectedSessionId);
return null;
}
}).when(mockApplicationEventPublisher).publishEvent(any(ApplicationEvent.class));
assertThat(sessionRepository.getSession(expectedSessionId)).isNull();
verify(mockTemplate, times(1)).get(eq(expectedSessionId));
verify(mockTemplate, times(1)).remove(eq(expectedSessionId));
verify(mockSession, times(1)).isExpired();
verify(mockSession, times(2)).getId();
verify(mockApplicationEventPublisher, times(1)).publishEvent(isA(SessionDeletedEvent.class));
}
@Test
public void getSessionFindsMatchingNonExpiredSessionById() {
final String expectedId = "1";
final long expectedCreationTime = System.currentTimeMillis();
final long currentLastAccessedTime = (expectedCreationTime + TimeUnit.MINUTES.toMillis(5));
ExpiringSession mockSession = mock(ExpiringSession.class);
when(mockSession.isExpired()).thenReturn(false);
when(mockSession.getId()).thenReturn(expectedId);
when(mockSession.getCreationTime()).thenReturn(expectedCreationTime);
when(mockSession.getLastAccessedTime()).thenReturn(currentLastAccessedTime);
when(mockSession.getAttributeNames()).thenReturn(Collections.singleton("attrOne"));
when(mockSession.getAttribute(eq("attrOne"))).thenReturn("test");
when(mockTemplate.get(eq(expectedId))).thenReturn(mockSession);
ExpiringSession actualSession = sessionRepository.getSession(expectedId);
assertThat(actualSession).isNotSameAs(mockSession);
assertThat(actualSession.getId()).isEqualTo(expectedId);
assertThat(actualSession.getCreationTime()).isEqualTo(expectedCreationTime);
assertThat(actualSession.getLastAccessedTime()).isNotEqualTo(currentLastAccessedTime);
assertThat(actualSession.getLastAccessedTime()).isGreaterThanOrEqualTo(expectedCreationTime);
assertThat(actualSession.getAttributeNames()).isEqualTo(Collections.singleton("attrOne"));
assertThat(String.valueOf(actualSession.getAttribute("attrOne"))).isEqualTo("test");
verify(mockTemplate, times(1)).get(eq(expectedId));
verify(mockSession, times(1)).isExpired();
verify(mockSession, times(1)).getId();
verify(mockSession, times(1)).getCreationTime();
verify(mockSession, times(1)).getLastAccessedTime();
verify(mockSession, times(1)).getAttributeNames();
verify(mockSession, times(1)).getAttribute(eq("attrOne"));
}
@Test
public void getSessionReturnsNull() {
when(mockTemplate.get(anyString())).thenReturn(null);
assertThat(sessionRepository.getSession("1")).isNull();
}
@Test
public void saveStoresSession() {
final String expectedSessionId = "1";
final long expectedCreationTime = System.currentTimeMillis();
final long expectedLastAccessTime = (expectedCreationTime + TimeUnit.MINUTES.toMillis(5));
ExpiringSession mockSession = mock(ExpiringSession.class);
when(mockSession.getId()).thenReturn(expectedSessionId);
when(mockSession.getCreationTime()).thenReturn(expectedCreationTime);
when(mockSession.getLastAccessedTime()).thenReturn(expectedLastAccessTime);
when(mockSession.getMaxInactiveIntervalInSeconds()).thenReturn(MAX_INACTIVE_INTERVAL_IN_SECONDS);
when(mockSession.getAttributeNames()).thenReturn(Collections.<String>emptySet());
when(mockTemplate.put(eq(expectedSessionId), isA(GemFireSession.class)))
.thenAnswer(new Answer<ExpiringSession>() {
public ExpiringSession answer(final InvocationOnMock invocation) throws Throwable {
ExpiringSession session = invocation.getArgumentAt(1, ExpiringSession.class);
assertThat(session).isNotNull();
assertThat(session.getId()).isEqualTo(expectedSessionId);
assertThat(session.getCreationTime()).isEqualTo(expectedCreationTime);
assertThat(session.getLastAccessedTime()).isEqualTo(expectedLastAccessTime);
assertThat(session.getMaxInactiveIntervalInSeconds()).isEqualTo(MAX_INACTIVE_INTERVAL_IN_SECONDS);
assertThat(session.getAttributeNames().isEmpty()).isTrue();
return null;
}
});
sessionRepository.save(mockSession);
verify(mockSession, times(2)).getId();
verify(mockSession, times(1)).getCreationTime();
verify(mockSession, times(1)).getLastAccessedTime();
verify(mockSession, times(1)).getMaxInactiveIntervalInSeconds();
verify(mockSession, times(1)).getAttributeNames();
verify(mockTemplate, times(1)).put(eq(expectedSessionId), isA(GemFireSession.class));
}
@Test
public void deleteRemovesExistingSessionAndHandlesDelete() {
final String expectedSessionId = "1";
final ExpiringSession mockSession = mock(ExpiringSession.class);
when(mockSession.getId()).thenReturn(expectedSessionId);
when(mockTemplate.remove(eq(expectedSessionId))).thenReturn(mockSession);
doAnswer(new Answer<Void>() {
public Void answer(final InvocationOnMock invocation) throws Throwable {
ApplicationEvent applicationEvent = invocation.getArgumentAt(0, ApplicationEvent.class);
assertThat(applicationEvent).isInstanceOf(SessionDeletedEvent.class);
AbstractSessionEvent sessionEvent = (AbstractSessionEvent) applicationEvent;
assertThat(sessionEvent.getSource()).isSameAs(sessionRepository);
assertThat(sessionEvent.getSession()).isSameAs(mockSession);
assertThat(sessionEvent.getSessionId()).isEqualTo(expectedSessionId);
return null;
}
}).when(mockApplicationEventPublisher).publishEvent(isA(SessionDeletedEvent.class));
sessionRepository.delete(expectedSessionId);
verify(mockSession, times(1)).getId();
verify(mockTemplate, times(1)).remove(eq(expectedSessionId));
verify(mockApplicationEventPublisher, times(1)).publishEvent(isA(SessionDeletedEvent.class));
}
@Test
public void deleteRemovesNonExistingSessionAndHandlesDelete() {
final String expectedSessionId = "1";
when(mockTemplate.remove(anyString())).thenReturn(null);
doAnswer(new Answer<Void>() {
public Void answer(final InvocationOnMock invocation) throws Throwable {
ApplicationEvent applicationEvent = invocation.getArgumentAt(0, ApplicationEvent.class);
assertThat(applicationEvent).isInstanceOf(SessionDeletedEvent.class);
AbstractSessionEvent sessionEvent = (AbstractSessionEvent) applicationEvent;
assertThat(sessionEvent.getSource()).isSameAs(sessionRepository);
assertThat(sessionEvent.getSession()).isNull();
assertThat(sessionEvent.getSessionId()).isEqualTo(expectedSessionId);
return null;
}
}).when(mockApplicationEventPublisher).publishEvent(isA(SessionDeletedEvent.class));
sessionRepository.delete(expectedSessionId);
verify(mockTemplate, times(1)).remove(eq(expectedSessionId));
verify(mockApplicationEventPublisher, times(1)).publishEvent(isA(SessionDeletedEvent.class));
}
protected abstract class GemfireOperationsAccessor extends GemfireAccessor implements GemfireOperations {
}
}

View File

@@ -0,0 +1,255 @@
/*
* Copyright 2002-2015 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.config.annotation.web.http;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import java.util.HashMap;
import java.util.Map;
import org.junit.Before;
import org.junit.Test;
import org.springframework.core.type.AnnotationMetadata;
import org.springframework.data.gemfire.GemfireOperations;
import org.springframework.data.gemfire.GemfireTemplate;
import org.springframework.session.data.gemfire.GemFireOperationsSessionRepository;
import com.gemstone.gemfire.cache.Cache;
import com.gemstone.gemfire.cache.GemFireCache;
import com.gemstone.gemfire.cache.Region;
import com.gemstone.gemfire.cache.RegionShortcut;
import com.gemstone.gemfire.cache.client.ClientCache;
import com.gemstone.gemfire.cache.client.ClientRegionShortcut;
/**
* The GemFireHttpSessionConfigurationTest class is a test suite of test cases testing the contract and functionality
* of the {@link GemFireHttpSessionConfiguration} class.
*
* @author John Blum
* @see org.junit.Test
* @see org.mockito.Mockito
* @see org.springframework.session.data.gemfire.config.annotation.web.http.GemFireHttpSessionConfiguration
* @see com.gemstone.gemfire.cache.Cache
* @see com.gemstone.gemfire.cache.GemFireCache
* @see com.gemstone.gemfire.cache.Region
* @see com.gemstone.gemfire.cache.client.ClientCache
* @since 1.0.0
*/
public class GemFireHttpSessionConfigurationTest {
private GemFireHttpSessionConfiguration gemfireConfiguration;
@Before
public void setup() {
gemfireConfiguration = new GemFireHttpSessionConfiguration();
}
@Test
public void setAndGetBeanClassLoader() {
assertThat(gemfireConfiguration.getBeanClassLoader()).isNull();
gemfireConfiguration.setBeanClassLoader(Thread.currentThread().getContextClassLoader());
assertThat(gemfireConfiguration.getBeanClassLoader()).isEqualTo(Thread.currentThread().getContextClassLoader());
gemfireConfiguration.setBeanClassLoader(null);
assertThat(gemfireConfiguration.getBeanClassLoader()).isNull();
}
@Test
public void setAndGetClientRegionShortcut() {
assertThat(gemfireConfiguration.getClientRegionShortcut()).isEqualTo(
GemFireHttpSessionConfiguration.DEFAULT_CLIENT_REGION_SHORTCUT);
gemfireConfiguration.setClientRegionShortcut(ClientRegionShortcut.CACHING_PROXY);
assertThat(gemfireConfiguration.getClientRegionShortcut()).isEqualTo(ClientRegionShortcut.CACHING_PROXY);
gemfireConfiguration.setClientRegionShortcut(null);
assertThat(gemfireConfiguration.getClientRegionShortcut()).isEqualTo(
GemFireHttpSessionConfiguration.DEFAULT_CLIENT_REGION_SHORTCUT);
}
@Test
public void setAndGetMaxInactiveIntervalInSeconds() {
assertThat(gemfireConfiguration.getMaxInactiveIntervalInSeconds()).isEqualTo(
GemFireHttpSessionConfiguration.DEFAULT_MAX_INACTIVE_INTERVAL_IN_SECONDS);
gemfireConfiguration.setMaxInactiveIntervalInSeconds(300);
assertThat(gemfireConfiguration.getMaxInactiveIntervalInSeconds()).isEqualTo(300);
gemfireConfiguration.setMaxInactiveIntervalInSeconds(Integer.MAX_VALUE);
assertThat(gemfireConfiguration.getMaxInactiveIntervalInSeconds()).isEqualTo(Integer.MAX_VALUE);
gemfireConfiguration.setMaxInactiveIntervalInSeconds(-1);
assertThat(gemfireConfiguration.getMaxInactiveIntervalInSeconds()).isEqualTo(-1);
gemfireConfiguration.setMaxInactiveIntervalInSeconds(Integer.MIN_VALUE);
assertThat(gemfireConfiguration.getMaxInactiveIntervalInSeconds()).isEqualTo(Integer.MIN_VALUE);
}
@Test
public void setAndGetServerRegionShortcut() {
assertThat(gemfireConfiguration.getServerRegionShortcut()).isEqualTo(
GemFireHttpSessionConfiguration.DEFAULT_SERVER_REGION_SHORTCUT);
gemfireConfiguration.setServerRegionShortcut(RegionShortcut.REPLICATE_PERSISTENT);
assertThat(gemfireConfiguration.getServerRegionShortcut()).isEqualTo(RegionShortcut.REPLICATE_PERSISTENT);
gemfireConfiguration.setServerRegionShortcut(null);
assertThat(gemfireConfiguration.getServerRegionShortcut()).isEqualTo(
GemFireHttpSessionConfiguration.DEFAULT_SERVER_REGION_SHORTCUT);
}
@Test
public void setAndGetSpringSessionGemFireRegionName() {
assertThat(gemfireConfiguration.getSpringSessionGemFireRegionName()).isEqualTo(
GemFireHttpSessionConfiguration.DEFAULT_SPRING_SESSION_GEMFIRE_REGION_NAME);
gemfireConfiguration.setSpringSessionGemFireRegionName("test");
assertThat(gemfireConfiguration.getSpringSessionGemFireRegionName()).isEqualTo("test");
gemfireConfiguration.setSpringSessionGemFireRegionName(" ");
assertThat(gemfireConfiguration.getSpringSessionGemFireRegionName()).isEqualTo(
GemFireHttpSessionConfiguration.DEFAULT_SPRING_SESSION_GEMFIRE_REGION_NAME);
gemfireConfiguration.setSpringSessionGemFireRegionName("");
assertThat(gemfireConfiguration.getSpringSessionGemFireRegionName()).isEqualTo(
GemFireHttpSessionConfiguration.DEFAULT_SPRING_SESSION_GEMFIRE_REGION_NAME);
gemfireConfiguration.setSpringSessionGemFireRegionName(null);
assertThat(gemfireConfiguration.getSpringSessionGemFireRegionName()).isEqualTo(
GemFireHttpSessionConfiguration.DEFAULT_SPRING_SESSION_GEMFIRE_REGION_NAME);
}
@Test
public void setImportMetadata() {
AnnotationMetadata mockAnnotationMetadata = mock(AnnotationMetadata.class, "testSetImportMetadata");
Map<String, Object> annotationAttributes = new HashMap<String, Object>(4);
annotationAttributes.put("clientRegionShortcut", ClientRegionShortcut.CACHING_PROXY);
annotationAttributes.put("maxInactiveIntervalInSeconds", 600);
annotationAttributes.put("serverRegionShortcut", RegionShortcut.REPLICATE);
annotationAttributes.put("regionName", "TEST");
when(mockAnnotationMetadata.getAnnotationAttributes(eq(EnableGemFireHttpSession.class.getName())))
.thenReturn(annotationAttributes);
gemfireConfiguration.setImportMetadata(mockAnnotationMetadata);
assertThat(gemfireConfiguration.getClientRegionShortcut()).isEqualTo(ClientRegionShortcut.CACHING_PROXY);
assertThat(gemfireConfiguration.getMaxInactiveIntervalInSeconds()).isEqualTo(600);
assertThat(gemfireConfiguration.getServerRegionShortcut()).isEqualTo(RegionShortcut.REPLICATE);
assertThat(gemfireConfiguration.getSpringSessionGemFireRegionName()).isEqualTo("TEST");
verify(mockAnnotationMetadata, times(1)).getAnnotationAttributes(eq(EnableGemFireHttpSession.class.getName()));
}
@Test
public void createAndInitializeSpringSessionRepositoryBean() {
GemfireOperations mockGemfireOperations = mock(GemfireOperations.class,
"testCreateAndInitializeSpringSessionRepositoryBean");
gemfireConfiguration.setMaxInactiveIntervalInSeconds(120);
GemFireOperationsSessionRepository sessionRepository = gemfireConfiguration.sessionRepository(
mockGemfireOperations);
assertThat(sessionRepository).isNotNull();
assertThat(sessionRepository.getTemplate()).isSameAs(mockGemfireOperations);
assertThat(sessionRepository.getMaxInactiveIntervalInSeconds()).isEqualTo(120);
}
@Test
@SuppressWarnings("unchecked")
public void createAndInitializeSpringSessionGemFireRegionTemplate() {
GemFireCache mockGemFireCache = mock(GemFireCache.class);
Region mockRegion = mock(Region.class);
when(mockGemFireCache.getRegion(eq("Example"))).thenReturn(mockRegion);
gemfireConfiguration.setSpringSessionGemFireRegionName("Example");
GemfireTemplate template = gemfireConfiguration.sessionRegionTemplate(mockGemFireCache);
assertThat(gemfireConfiguration.getSpringSessionGemFireRegionName()).isEqualTo("Example");
assertThat(template).isNotNull();
assertThat(template.getRegion()).isSameAs(mockRegion);
verify(mockGemFireCache, times(1)).getRegion(eq("Example"));
}
@Test
public void expirationIsAllowed() {
Cache mockCache = mock(Cache.class, "testExpirationIsAllowed.MockCache");
ClientCache mockClientCache = mock(ClientCache.class, "testExpirationIsAllowed.MockClientCache");
gemfireConfiguration.setClientRegionShortcut(ClientRegionShortcut.PROXY);
gemfireConfiguration.setServerRegionShortcut(RegionShortcut.REPLICATE);
assertThat(gemfireConfiguration.isExpirationAllowed(mockCache)).isTrue();
gemfireConfiguration.setServerRegionShortcut(RegionShortcut.PARTITION_REDUNDANT_PERSISTENT_OVERFLOW);
assertThat(gemfireConfiguration.isExpirationAllowed(mockCache)).isTrue();
gemfireConfiguration.setClientRegionShortcut(ClientRegionShortcut.CACHING_PROXY);
gemfireConfiguration.setServerRegionShortcut(RegionShortcut.PARTITION_PROXY);
assertThat(gemfireConfiguration.isExpirationAllowed(mockClientCache)).isTrue();
gemfireConfiguration.setClientRegionShortcut(ClientRegionShortcut.LOCAL_PERSISTENT_OVERFLOW);
gemfireConfiguration.setServerRegionShortcut(RegionShortcut.REPLICATE_PROXY);
assertThat(gemfireConfiguration.isExpirationAllowed(mockClientCache)).isTrue();
}
@Test
public void expirationIsNotAllowed() {
Cache mockCache = mock(Cache.class, "testExpirationIsAllowed.MockCache");
ClientCache mockClientCache = mock(ClientCache.class, "testExpirationIsAllowed.MockClientCache");
gemfireConfiguration.setClientRegionShortcut(ClientRegionShortcut.PROXY);
gemfireConfiguration.setServerRegionShortcut(RegionShortcut.PARTITION);
assertThat(gemfireConfiguration.isExpirationAllowed(mockClientCache)).isFalse();
gemfireConfiguration.setClientRegionShortcut(ClientRegionShortcut.LOCAL);
gemfireConfiguration.setServerRegionShortcut(RegionShortcut.PARTITION_PROXY);
assertThat(gemfireConfiguration.isExpirationAllowed(mockCache)).isFalse();
}
}

View File

@@ -0,0 +1,245 @@
/*
* Copyright 2002-2015 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.config.annotation.web.http.support;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.mock;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.springframework.data.gemfire.client.Interest;
import com.gemstone.gemfire.cache.Cache;
import com.gemstone.gemfire.cache.GemFireCache;
import com.gemstone.gemfire.cache.InterestResultPolicy;
import com.gemstone.gemfire.cache.Region;
import com.gemstone.gemfire.cache.RegionAttributes;
import com.gemstone.gemfire.cache.RegionShortcut;
import com.gemstone.gemfire.cache.client.ClientCache;
import com.gemstone.gemfire.cache.client.ClientRegionShortcut;
/**
* The GemFireCacheTypeAwareRegionFactoryBeanTest class is a test suite of test cases testing the contract
* and functionality of the GemFireCacheTypeAwareRegionFactoryBean class.
*
* @author John Blum
* @see org.junit.Rule
* @see org.junit.Test
* @see org.mockito.Mockito
* @see org.springframework.session.data.gemfire.config.annotation.web.http.support.GemFireCacheTypeAwareRegionFactoryBean
* @see com.gemstone.gemfire.cache.Cache
* @see com.gemstone.gemfire.cache.GemFireCache
* @see com.gemstone.gemfire.cache.InterestResultPolicy
* @see com.gemstone.gemfire.cache.Region
* @see com.gemstone.gemfire.cache.RegionAttributes
* @see com.gemstone.gemfire.cache.RegionShortcut
* @see com.gemstone.gemfire.cache.client.ClientCache
* @see com.gemstone.gemfire.cache.client.ClientRegionShortcut
* @since 1.0.0
*/
public class GemFireCacheTypeAwareRegionFactoryBeanTest {
@Rule
public ExpectedException expectedException = ExpectedException.none();
private GemFireCacheTypeAwareRegionFactoryBean regionFactoryBean;
@Before
public void setup() {
regionFactoryBean = new GemFireCacheTypeAwareRegionFactoryBean();
}
@Test
public void afterPropertiesSetCreatesClientRegionForClientCache() throws Exception {
final ClientCache mockClientCache = mock(ClientCache.class);
final Region mockClientRegion = mock(Region.class, "MockClientRegion");
final Region mockServerRegion = mock(Region.class, "MockServerRegion");
regionFactoryBean = new GemFireCacheTypeAwareRegionFactoryBean() {
@Override protected Region newClientRegion(GemFireCache gemfireCache) throws Exception {
assertThat(gemfireCache).isSameAs(mockClientCache);
return mockClientRegion;
}
@Override protected Region newServerRegion(final GemFireCache gemfireCache) throws Exception {
assertThat(gemfireCache).isSameAs(mockClientCache);
return mockServerRegion;
}
};
regionFactoryBean.setGemfireCache(mockClientCache);
regionFactoryBean.afterPropertiesSet();
assertThat(regionFactoryBean.getGemfireCache()).isSameAs(mockClientCache);
assertThat(regionFactoryBean.getObject()).isEqualTo(mockClientRegion);
}
@Test
public void afterPropertiesSetCreatesServerRegionForPeerCache() throws Exception {
final Cache mockCache = mock(Cache.class);
final Region mockClientRegion = mock(Region.class, "MockClientRegion");
final Region mockServerRegion = mock(Region.class, "MockServerRegion");
regionFactoryBean = new GemFireCacheTypeAwareRegionFactoryBean() {
@Override protected Region newClientRegion(GemFireCache gemfireCache) throws Exception {
assertThat(gemfireCache).isSameAs(mockCache);
return mockClientRegion;
}
@Override protected Region newServerRegion(final GemFireCache gemfireCache) throws Exception {
assertThat(gemfireCache).isSameAs(mockCache);
return mockServerRegion;
}
};
regionFactoryBean.setGemfireCache(mockCache);
regionFactoryBean.afterPropertiesSet();
assertThat(regionFactoryBean.getGemfireCache()).isSameAs(mockCache);
assertThat(regionFactoryBean.getObject()).isEqualTo(mockServerRegion);
}
@Test
public void allKeysInterestRegistration() {
Interest[] interests = regionFactoryBean.registerInterests(true);
assertThat(interests).isNotNull();
assertThat(interests.length).isEqualTo(1);
assertThat(interests[0].isDurable()).isFalse();
assertThat(interests[0].getKey().toString()).isEqualTo("ALL_KEYS");
assertThat(interests[0].getPolicy()).isEqualTo(InterestResultPolicy.KEYS);
assertThat(interests[0].isReceiveValues()).isTrue();
}
@Test
public void emptyInterestsRegistration() {
Interest[] interests = regionFactoryBean.registerInterests(false);
assertThat(interests).isNotNull();
assertThat(interests.length).isEqualTo(0);
}
@Test
@SuppressWarnings("unchecked")
public void getObjectTypeBeforeInitializationIsRegionClass() {
assertThat((Class<Region>) regionFactoryBean.getObjectType()).isEqualTo(Region.class);
}
@Test
public void isSingletonIsTrue() {
assertThat(regionFactoryBean.isSingleton()).isTrue();
}
@Test
public void setAndGetClientRegionShortcut() {
assertThat(regionFactoryBean.getClientRegionShortcut()).isEqualTo(
GemFireCacheTypeAwareRegionFactoryBean.DEFAULT_CLIENT_REGION_SHORTCUT);
regionFactoryBean.setClientRegionShortcut(ClientRegionShortcut.LOCAL_PERSISTENT);
assertThat(regionFactoryBean.getClientRegionShortcut()).isEqualTo(ClientRegionShortcut.LOCAL_PERSISTENT);
regionFactoryBean.setClientRegionShortcut(null);
assertThat(regionFactoryBean.getClientRegionShortcut()).isEqualTo(
GemFireCacheTypeAwareRegionFactoryBean.DEFAULT_CLIENT_REGION_SHORTCUT);
}
@Test
public void setAndGetGemfireCache() {
Cache mockCache = mock(Cache.class);
regionFactoryBean.setGemfireCache(mockCache);
assertThat(regionFactoryBean.getGemfireCache()).isEqualTo(mockCache);
}
@Test
public void setGemfireCacheToNullThrowsIllegalArgumentException() {
expectedException.expect(IllegalArgumentException.class);
expectedException.expectMessage("The GemFireCache reference must not be null");
regionFactoryBean.setGemfireCache(null);
}
@Test
public void getGemfireCacheWhenNullThrowsIllegalStateException() {
expectedException.expect(IllegalStateException.class);
expectedException.expectMessage("A reference to a GemFireCache was not properly configured");
regionFactoryBean.getGemfireCache();
}
@Test
@SuppressWarnings("unchecked")
public void setAndGetRegionAttributes() {
RegionAttributes mockRegionAttributes = mock(RegionAttributes.class);
assertThat(regionFactoryBean.getRegionAttributes()).isNull();
regionFactoryBean.setRegionAttributes(mockRegionAttributes);
assertThat(regionFactoryBean.getRegionAttributes()).isSameAs(mockRegionAttributes);
regionFactoryBean.setRegionAttributes(null);
assertThat(regionFactoryBean.getRegionAttributes()).isNull();
}
@Test
public void setAndGetRegionName() {
assertThat(regionFactoryBean.getRegionName()).isEqualTo(
GemFireCacheTypeAwareRegionFactoryBean.DEFAULT_SPRING_SESSION_GEMFIRE_REGION_NAME);
regionFactoryBean.setRegionName("Example");
assertThat(regionFactoryBean.getRegionName()).isEqualTo("Example");
regionFactoryBean.setRegionName(" ");
assertThat(regionFactoryBean.getRegionName()).isEqualTo(
GemFireCacheTypeAwareRegionFactoryBean.DEFAULT_SPRING_SESSION_GEMFIRE_REGION_NAME);
regionFactoryBean.setRegionName("");
assertThat(regionFactoryBean.getRegionName()).isEqualTo(
GemFireCacheTypeAwareRegionFactoryBean.DEFAULT_SPRING_SESSION_GEMFIRE_REGION_NAME);
regionFactoryBean.setRegionName(null);
assertThat(regionFactoryBean.getRegionName()).isEqualTo(
GemFireCacheTypeAwareRegionFactoryBean.DEFAULT_SPRING_SESSION_GEMFIRE_REGION_NAME);
}
@Test
public void setAndGetServerRegionShortcut() {
assertThat(regionFactoryBean.getServerRegionShortcut()).isEqualTo(
GemFireCacheTypeAwareRegionFactoryBean.DEFAULT_SERVER_REGION_SHORTCUT);
regionFactoryBean.setServerRegionShortcut(RegionShortcut.LOCAL_PERSISTENT);
assertThat(regionFactoryBean.getServerRegionShortcut()).isEqualTo(RegionShortcut.LOCAL_PERSISTENT);
regionFactoryBean.setServerRegionShortcut(null);
assertThat(regionFactoryBean.getServerRegionShortcut()).isEqualTo(
GemFireCacheTypeAwareRegionFactoryBean.DEFAULT_SERVER_REGION_SHORTCUT);
}
}

View File

@@ -0,0 +1,172 @@
/*
* Copyright 2002-2015 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.support;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import java.io.Closeable;
import java.io.IOException;
import org.junit.Test;
import com.gemstone.gemfire.cache.Cache;
import com.gemstone.gemfire.cache.GemFireCache;
import com.gemstone.gemfire.cache.RegionShortcut;
import com.gemstone.gemfire.cache.client.ClientCache;
import com.gemstone.gemfire.cache.client.ClientRegionShortcut;
/**
* The GemFireUtilsTest class is a test suite of test cases testing the contract and functionality of the GemFireUtils
* utility class.
*
* @author John Blum
* @see org.junit.Test
* @see org.mockito.Mockito
* @see org.springframework.session.data.gemfire.support.GemFireUtils
* @since 1.0.0
*/
public class GemFireUtilsTest {
@Test
public void closeNonNullCloseableSuccessfullyReturnsTrue() throws IOException {
Closeable mockCloseable = mock(Closeable.class);
assertThat(GemFireUtils.close(mockCloseable)).isTrue();
verify(mockCloseable, times(1)).close();
}
@Test
public void closeNonNullCloseableObjectThrowingIOExceptionReturnsFalse() throws IOException {
Closeable mockCloseable = mock(Closeable.class);
doThrow(new IOException("test")).when(mockCloseable).close();
assertThat(GemFireUtils.close(mockCloseable)).isFalse();
verify(mockCloseable, times(1)).close();
}
@Test
public void closeNullCloseableObjectReturnsFalse() {
assertThat(GemFireUtils.close(null)).isFalse();
}
@Test
public void clientCacheIsClient() {
assertThat(GemFireUtils.isClient(mock(ClientCache.class))).isTrue();
}
@Test
public void genericCacheIsNotClient() {
assertThat(GemFireUtils.isClient(mock(GemFireCache.class))).isFalse();
}
@Test
public void peerCacheIsNotClient() {
assertThat(GemFireUtils.isClient(mock(Cache.class))).isFalse();
}
@Test
public void peerCacheIsPeer() {
assertThat(GemFireUtils.isPeer(mock(Cache.class))).isTrue();
}
@Test
public void genericCacheIsNotPeer() {
assertThat(GemFireUtils.isPeer(mock(GemFireCache.class))).isFalse();
}
@Test
public void clientCacheIsNotPeer() {
assertThat(GemFireUtils.isPeer(mock(ClientCache.class))).isFalse();
}
@Test
public void clientRegionShortcutIsLocal() {
assertThat(GemFireUtils.isLocal(ClientRegionShortcut.LOCAL)).isTrue();
assertThat(GemFireUtils.isLocal(ClientRegionShortcut.LOCAL_HEAP_LRU)).isTrue();
assertThat(GemFireUtils.isLocal(ClientRegionShortcut.LOCAL_OVERFLOW)).isTrue();
assertThat(GemFireUtils.isLocal(ClientRegionShortcut.LOCAL_PERSISTENT)).isTrue();
assertThat(GemFireUtils.isLocal(ClientRegionShortcut.LOCAL_PERSISTENT_OVERFLOW)).isTrue();
}
@Test
public void clientRegionShortcutIsNotLocal() {
assertThat(GemFireUtils.isLocal(ClientRegionShortcut.CACHING_PROXY)).isFalse();
assertThat(GemFireUtils.isLocal(ClientRegionShortcut.CACHING_PROXY_HEAP_LRU)).isFalse();
assertThat(GemFireUtils.isLocal(ClientRegionShortcut.CACHING_PROXY_OVERFLOW)).isFalse();
assertThat(GemFireUtils.isLocal(ClientRegionShortcut.PROXY)).isFalse();
}
@Test
public void clientRegionShortcutIsProxy() {
assertThat(GemFireUtils.isProxy(ClientRegionShortcut.PROXY)).isTrue();
}
@Test
public void clientRegionShortcutIsNotProxy() {
assertThat(GemFireUtils.isProxy(ClientRegionShortcut.CACHING_PROXY)).isFalse();
assertThat(GemFireUtils.isProxy(ClientRegionShortcut.CACHING_PROXY_HEAP_LRU)).isFalse();
assertThat(GemFireUtils.isProxy(ClientRegionShortcut.CACHING_PROXY_OVERFLOW)).isFalse();
assertThat(GemFireUtils.isProxy(ClientRegionShortcut.LOCAL)).isFalse();
assertThat(GemFireUtils.isProxy(ClientRegionShortcut.LOCAL_HEAP_LRU)).isFalse();
assertThat(GemFireUtils.isProxy(ClientRegionShortcut.LOCAL_OVERFLOW)).isFalse();
assertThat(GemFireUtils.isProxy(ClientRegionShortcut.LOCAL_PERSISTENT)).isFalse();
assertThat(GemFireUtils.isProxy(ClientRegionShortcut.LOCAL_PERSISTENT_OVERFLOW)).isFalse();
}
@Test
public void regionShortcutIsProxy() {
assertThat(GemFireUtils.isProxy(RegionShortcut.PARTITION_PROXY)).isTrue();
assertThat(GemFireUtils.isProxy(RegionShortcut.PARTITION_PROXY_REDUNDANT)).isTrue();
assertThat(GemFireUtils.isProxy(RegionShortcut.REPLICATE_PROXY)).isTrue();
}
@Test
public void regionShortcutIsNotProxy() {
assertThat(GemFireUtils.isProxy(RegionShortcut.LOCAL)).isFalse();
assertThat(GemFireUtils.isProxy(RegionShortcut.LOCAL_HEAP_LRU)).isFalse();
assertThat(GemFireUtils.isProxy(RegionShortcut.LOCAL_OVERFLOW)).isFalse();
assertThat(GemFireUtils.isProxy(RegionShortcut.LOCAL_PERSISTENT)).isFalse();
assertThat(GemFireUtils.isProxy(RegionShortcut.LOCAL_PERSISTENT_OVERFLOW)).isFalse();
assertThat(GemFireUtils.isProxy(RegionShortcut.REPLICATE)).isFalse();
assertThat(GemFireUtils.isProxy(RegionShortcut.REPLICATE_HEAP_LRU)).isFalse();
assertThat(GemFireUtils.isProxy(RegionShortcut.REPLICATE_OVERFLOW)).isFalse();
assertThat(GemFireUtils.isProxy(RegionShortcut.REPLICATE_PERSISTENT)).isFalse();
assertThat(GemFireUtils.isProxy(RegionShortcut.REPLICATE_PERSISTENT_OVERFLOW)).isFalse();
assertThat(GemFireUtils.isProxy(RegionShortcut.PARTITION)).isFalse();
assertThat(GemFireUtils.isProxy(RegionShortcut.PARTITION_HEAP_LRU)).isFalse();
assertThat(GemFireUtils.isProxy(RegionShortcut.PARTITION_OVERFLOW)).isFalse();
assertThat(GemFireUtils.isProxy(RegionShortcut.PARTITION_PERSISTENT)).isFalse();
assertThat(GemFireUtils.isProxy(RegionShortcut.PARTITION_PERSISTENT_OVERFLOW)).isFalse();
assertThat(GemFireUtils.isProxy(RegionShortcut.PARTITION_REDUNDANT)).isFalse();
assertThat(GemFireUtils.isProxy(RegionShortcut.PARTITION_REDUNDANT_HEAP_LRU)).isFalse();
assertThat(GemFireUtils.isProxy(RegionShortcut.PARTITION_REDUNDANT_OVERFLOW)).isFalse();
assertThat(GemFireUtils.isProxy(RegionShortcut.PARTITION_REDUNDANT_PERSISTENT)).isFalse();
assertThat(GemFireUtils.isProxy(RegionShortcut.PARTITION_REDUNDANT_PERSISTENT_OVERFLOW)).isFalse();
}
@Test
public void toRegionPath() {
assertThat(GemFireUtils.toRegionPath("A")).isEqualTo("/A");
assertThat(GemFireUtils.toRegionPath("Example")).isEqualTo("/Example");
assertThat(GemFireUtils.toRegionPath("/Example")).isEqualTo("//Example");
assertThat(GemFireUtils.toRegionPath("/")).isEqualTo("//");
assertThat(GemFireUtils.toRegionPath("")).isEqualTo("/");
}
}