GEODE:6784 Added unit tests to classes in the tomcat module (#4061)
Co-authored-by: Benjamin Ross <bross@pivotal.io>
Co-authored-by: Donal Evans <doevans@pivotal.io>
diff --git a/extensions/geode-modules-test/src/main/java/org/apache/geode/modules/session/catalina/AbstractSessionCacheJUnitTest.java b/extensions/geode-modules-test/src/main/java/org/apache/geode/modules/session/catalina/AbstractSessionCacheJUnitTest.java
new file mode 100644
index 0000000..04cc183
--- /dev/null
+++ b/extensions/geode-modules-test/src/main/java/org/apache/geode/modules/session/catalina/AbstractSessionCacheJUnitTest.java
@@ -0,0 +1,124 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more contributor license
+ * agreements. See the NOTICE file distributed with this work for additional information regarding
+ * copyright ownership. The ASF licenses this file to You 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.apache.geode.modules.session.catalina;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.doThrow;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import javax.servlet.http.HttpSession;
+
+import org.apache.juli.logging.Log;
+import org.junit.Test;
+
+import org.apache.geode.cache.CustomExpiry;
+import org.apache.geode.cache.EntryNotFoundException;
+import org.apache.geode.cache.Region;
+import org.apache.geode.cache.RegionShortcut;
+import org.apache.geode.cache.execute.Execution;
+import org.apache.geode.distributed.DistributedSystem;
+import org.apache.geode.modules.util.RegionConfiguration;
+
+public abstract class AbstractSessionCacheJUnitTest {
+
+ protected String sessionRegionName = "sessionRegion";
+ private String sessionRegionAttributesId = RegionShortcut.PARTITION.toString();
+ private int nonDefaultMaxInactiveInterval = RegionConfiguration.DEFAULT_MAX_INACTIVE_INTERVAL + 1;
+ private boolean gatewayDeltaReplicationEnabled = true;
+ private boolean gatewayReplicationEnabled = true;
+ private boolean enableDebugListener = true;
+
+
+ protected SessionManager sessionManager = mock(SessionManager.class);
+ @SuppressWarnings("unchecked")
+ protected Region<String, HttpSession> sessionRegion = mock(Region.class);
+ protected DistributedSystem distributedSystem = mock(DistributedSystem.class);
+ protected Log logger = mock(Log.class);
+ protected Execution emptyExecution = mock(Execution.class);
+
+ protected AbstractSessionCache sessionCache;
+
+ @Test
+ public void createRegionConfigurationSetsAppropriateValuesWithDefaultMaxInactiveInterval() {
+ RegionConfiguration config = spy(new RegionConfiguration());
+ doReturn(config).when(sessionCache).getNewRegionConfiguration();
+
+ when(sessionManager.getRegionName()).thenReturn(sessionRegionName);
+ when(sessionManager.getRegionAttributesId()).thenReturn(sessionRegionAttributesId);
+ when(sessionManager.getMaxInactiveInterval())
+ .thenReturn(RegionConfiguration.DEFAULT_MAX_INACTIVE_INTERVAL);
+ when(sessionManager.getEnableGatewayDeltaReplication())
+ .thenReturn(gatewayDeltaReplicationEnabled);
+ when(sessionManager.getEnableGatewayReplication()).thenReturn(gatewayReplicationEnabled);
+ when(sessionManager.getEnableDebugListener()).thenReturn(enableDebugListener);
+
+ sessionCache.createRegionConfiguration();
+
+ verify(config).setRegionName(sessionRegionName);
+ verify(config).setRegionAttributesId(sessionRegionAttributesId);
+ verify(config, times(0)).setMaxInactiveInterval(anyInt());
+ verify(config, times(0)).setCustomExpiry(any(CustomExpiry.class));
+ verify(config).setEnableGatewayDeltaReplication(gatewayDeltaReplicationEnabled);
+ verify(config).setEnableGatewayReplication(gatewayReplicationEnabled);
+ verify(config).setEnableDebugListener(enableDebugListener);
+ }
+
+ @Test
+ public void createRegionConfigurationSetsAppropriateValuesWithNonDefaultMaxInactiveInterval() {
+ RegionConfiguration config = spy(new RegionConfiguration());
+ doReturn(config).when(sessionCache).getNewRegionConfiguration();
+
+ when(sessionManager.getRegionName()).thenReturn(sessionRegionName);
+ when(sessionManager.getRegionAttributesId()).thenReturn(sessionRegionAttributesId);
+ when(sessionManager.getMaxInactiveInterval()).thenReturn(nonDefaultMaxInactiveInterval);
+ when(sessionManager.getEnableGatewayDeltaReplication())
+ .thenReturn(gatewayDeltaReplicationEnabled);
+ when(sessionManager.getEnableGatewayReplication()).thenReturn(gatewayReplicationEnabled);
+ when(sessionManager.getEnableDebugListener()).thenReturn(enableDebugListener);
+
+ sessionCache.createRegionConfiguration();
+
+ verify(config).setRegionName(sessionRegionName);
+ verify(config).setRegionAttributesId(sessionRegionAttributesId);
+ verify(config).setMaxInactiveInterval(nonDefaultMaxInactiveInterval);
+ verify(config).setCustomExpiry(any(CustomExpiry.class));
+ verify(config).setEnableGatewayDeltaReplication(gatewayDeltaReplicationEnabled);
+ verify(config).setEnableGatewayReplication(gatewayReplicationEnabled);
+ verify(config).setEnableDebugListener(enableDebugListener);
+ }
+
+ @Test
+ public void destroySessionDoesNotThrowExceptionWhenGetOperatingRegionThrowsEntryNotFoundException() {
+ EntryNotFoundException exception = new EntryNotFoundException("Entry not found.");
+ String sessionId = "sessionId";
+ // For Client/Server the operating Region is always the session Region, for peer to peer this is
+ // only true when
+ // local caching is not enabled. For the purposes of this test the behavior is equivalent
+ // regardless of local
+ // caching.
+ when(sessionCache.getOperatingRegion()).thenReturn(sessionRegion);
+ doThrow(exception).when(sessionRegion).destroy(sessionId);
+
+ sessionCache.destroySession(sessionId);
+ verify(sessionCache).getOperatingRegion();
+ }
+}
diff --git a/extensions/geode-modules-test/src/main/java/org/apache/geode/modules/session/catalina/ClientServerSessionCacheJUnitTest.java b/extensions/geode-modules-test/src/main/java/org/apache/geode/modules/session/catalina/ClientServerSessionCacheJUnitTest.java
new file mode 100644
index 0000000..2e34681
--- /dev/null
+++ b/extensions/geode-modules-test/src/main/java/org/apache/geode/modules/session/catalina/ClientServerSessionCacheJUnitTest.java
@@ -0,0 +1,318 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more contributor license
+ * agreements. See the NOTICE file distributed with this work for additional information regarding
+ * copyright ownership. The ASF licenses this file to You 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.apache.geode.modules.session.catalina;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+import static org.mockito.Mockito.any;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.doThrow;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import javax.servlet.http.HttpSession;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.ArgumentCaptor;
+
+import org.apache.geode.Statistics;
+import org.apache.geode.cache.AttributesMutator;
+import org.apache.geode.cache.CacheListener;
+import org.apache.geode.cache.DataPolicy;
+import org.apache.geode.cache.InterestResultPolicy;
+import org.apache.geode.cache.RegionAttributes;
+import org.apache.geode.cache.RegionShortcut;
+import org.apache.geode.cache.client.ClientCache;
+import org.apache.geode.cache.client.ClientRegionFactory;
+import org.apache.geode.cache.client.ClientRegionShortcut;
+import org.apache.geode.cache.client.internal.InternalClientCache;
+import org.apache.geode.cache.client.internal.PoolImpl;
+import org.apache.geode.cache.execute.Function;
+import org.apache.geode.cache.execute.FunctionException;
+import org.apache.geode.cache.execute.ResultCollector;
+import org.apache.geode.internal.cache.GemFireCacheImpl;
+import org.apache.geode.modules.session.catalina.callback.SessionExpirationCacheListener;
+import org.apache.geode.modules.util.BootstrappingFunction;
+import org.apache.geode.modules.util.CreateRegionFunction;
+import org.apache.geode.modules.util.DebugCacheListener;
+import org.apache.geode.modules.util.RegionConfiguration;
+import org.apache.geode.modules.util.RegionStatus;
+import org.apache.geode.modules.util.SessionCustomExpiry;
+import org.apache.geode.modules.util.TouchPartitionedRegionEntriesFunction;
+import org.apache.geode.modules.util.TouchReplicatedRegionEntriesFunction;
+
+public class ClientServerSessionCacheJUnitTest extends AbstractSessionCacheJUnitTest {
+
+ private List<RegionStatus> regionStatusResultList = new ArrayList<>();
+ private ClientCache cache = mock(GemFireCacheImpl.class);
+ private ResultCollector collector = mock(ResultCollector.class);
+ private Statistics stats = mock(Statistics.class);
+ @SuppressWarnings("unchecked")
+ private ClientRegionFactory<String, HttpSession> regionFactory = mock(ClientRegionFactory.class);
+ @SuppressWarnings("unchecked")
+ private RegionAttributes<String, HttpSession> attributes = mock(RegionAttributes.class);
+
+ @Before
+ public void setUp() {
+ sessionCache = spy(new ClientServerSessionCache(sessionManager, cache));
+ doReturn(emptyExecution).when((ClientServerSessionCache) sessionCache)
+ .getExecutionForFunctionOnServers();
+ doReturn(emptyExecution).when((ClientServerSessionCache) sessionCache)
+ .getExecutionForFunctionOnServersWithArguments(any());
+ doReturn(emptyExecution).when((ClientServerSessionCache) sessionCache)
+ .getExecutionForFunctionOnServerWithRegionConfiguration(any());
+ doReturn(emptyExecution).when((ClientServerSessionCache) sessionCache)
+ .getExecutionForFunctionOnRegionWithFilter(any());
+
+ when(sessionManager.getLogger()).thenReturn(logger);
+ when(sessionManager.getEnableLocalCache()).thenReturn(true);
+ when(sessionManager.getRegionName()).thenReturn(sessionRegionName);
+ when(sessionManager.getMaxInactiveInterval())
+ .thenReturn(RegionConfiguration.DEFAULT_MAX_INACTIVE_INTERVAL);
+
+ when(cache.getDistributedSystem()).thenReturn(distributedSystem);
+ doReturn(regionFactory).when(cache)
+ .createClientRegionFactory(ClientRegionShortcut.CACHING_PROXY_HEAP_LRU);
+ when(((InternalClientCache) cache).isClient()).thenReturn(true);
+
+ when(emptyExecution.execute(any(Function.class))).thenReturn(collector);
+ when(emptyExecution.execute(any(String.class))).thenReturn(collector);
+
+ when(collector.getResult()).thenReturn(regionStatusResultList);
+
+ when(distributedSystem.createAtomicStatistics(any(), any())).thenReturn(stats);
+
+ regionStatusResultList.clear();
+ regionStatusResultList.add(RegionStatus.VALID);
+ }
+
+ @Test
+ public void initializeSessionCacheSucceeds() {
+ sessionCache.initialize();
+
+ verify(emptyExecution).execute(any(BootstrappingFunction.class));
+ verify(emptyExecution).execute(CreateRegionFunction.ID);
+ verify(cache).createClientRegionFactory(ClientRegionShortcut.CACHING_PROXY_HEAP_LRU);
+ verify(regionFactory, times(0)).setStatisticsEnabled(true);
+ verify(regionFactory, times(0)).setCustomEntryIdleTimeout(any(SessionCustomExpiry.class));
+ verify(regionFactory, times(0)).addCacheListener(any(SessionExpirationCacheListener.class));
+ verify(regionFactory).create(sessionRegionName);
+ }
+
+ @Test
+ public void bootstrappingFunctionThrowsException() {
+ FunctionException exception = new FunctionException();
+
+ ResultCollector exceptionCollector = mock(ResultCollector.class);
+
+ when(emptyExecution.execute(new BootstrappingFunction())).thenReturn(exceptionCollector);
+ when(exceptionCollector.getResult()).thenThrow(exception);
+
+ sessionCache.initialize();
+
+ verify(logger).warn("Caught unexpected exception:", exception);
+ }
+
+
+ @Test
+ public void createOrRetrieveRegionThrowsException() {
+ RuntimeException exception = new RuntimeException();
+ doThrow(exception).when((ClientServerSessionCache) sessionCache).createLocalSessionRegion();
+
+ assertThatThrownBy(() -> sessionCache.initialize()).hasCause(exception)
+ .isInstanceOf(IllegalStateException.class);
+
+ verify(logger).fatal("Unable to create or retrieve region", exception);
+
+ }
+
+ @Test
+ public void createRegionFunctionFailsOnServer() {
+ ArgumentCaptor<String> stringCaptor = ArgumentCaptor.forClass(String.class);
+
+ regionStatusResultList.clear();
+ regionStatusResultList.add(RegionStatus.INVALID);
+
+ assertThatThrownBy(() -> sessionCache.initialize()).isInstanceOf(IllegalStateException.class)
+ .hasCauseInstanceOf(IllegalStateException.class).hasMessageContaining(
+ "An exception occurred on the server while attempting to create or validate region named "
+ + sessionRegionName
+ + ". See the server log for additional details.");
+
+ verify(logger).fatal(stringCaptor.capture(), any(Exception.class));
+ assertThat(stringCaptor.getValue()).isEqualTo("Unable to create or retrieve region");
+ }
+
+ @Test
+ public void nonDefaultMaxTimeoutIntervalSetsExpirationDetails() {
+ // Setting the mocked return value of getMaxInactiveInterval to something distinctly not equal
+ // to the default
+ when(sessionManager.getMaxInactiveInterval())
+ .thenReturn(RegionConfiguration.DEFAULT_MAX_INACTIVE_INTERVAL + 1);
+
+ sessionCache.initialize();
+
+ verify(regionFactory).setStatisticsEnabled(true);
+ verify(regionFactory).setCustomEntryIdleTimeout(any(SessionCustomExpiry.class));
+ verify(regionFactory).addCacheListener(any(SessionExpirationCacheListener.class));
+ }
+
+ @Test
+ public void createLocalSessionRegionWithoutEnableLocalCache() {
+ when(sessionManager.getEnableLocalCache()).thenReturn(false);
+ doReturn(regionFactory).when(cache).createClientRegionFactory(ClientRegionShortcut.PROXY);
+ when(regionFactory.create(sessionRegionName)).thenReturn(sessionRegion);
+
+ sessionCache.initialize();
+
+ verify(regionFactory).addCacheListener(any(SessionExpirationCacheListener.class));
+ verify(sessionRegion).registerInterest("ALL_KEYS", InterestResultPolicy.KEYS);
+ }
+
+ @Test
+ public void createOrRetrieveRegionWithNonNullSessionRegionDoesNotCreateRegion() {
+ @SuppressWarnings("unchecked")
+ CacheListener<String, HttpSession>[] cacheListeners =
+ new CacheListener[] {new SessionExpirationCacheListener()};
+ doReturn(sessionRegion).when(cache).getRegion(sessionRegionName);
+ doReturn(attributes).when(sessionRegion).getAttributes();
+ doReturn(cacheListeners).when(attributes).getCacheListeners();
+
+ sessionCache.initialize();
+
+ verify((ClientServerSessionCache) sessionCache, times(0)).createSessionRegionOnServers();
+ verify((ClientServerSessionCache) sessionCache, times(0)).createLocalSessionRegion();
+ }
+
+ @Test
+ public void createOrRetrieveRegionWithNonNullSessionRegionAndNoSessionExpirationCacheListenerCreatesListener() {
+ @SuppressWarnings("unchecked")
+ CacheListener<String, HttpSession>[] cacheListeners =
+ new CacheListener[] {new DebugCacheListener()};
+ @SuppressWarnings("unchecked")
+ AttributesMutator<String, HttpSession> attributesMutator = mock(AttributesMutator.class);
+ doReturn(sessionRegion).when(cache).getRegion(sessionRegionName);
+ doReturn(attributes).when(sessionRegion).getAttributes();
+ doReturn(cacheListeners).when(attributes).getCacheListeners();
+ doReturn(attributesMutator).when(sessionRegion).getAttributesMutator();
+
+ sessionCache.initialize();
+
+ verify(attributesMutator).addCacheListener(any(SessionExpirationCacheListener.class));
+ }
+
+ @Test
+ public void createOrRetrieveRegionWithNonNullSessionProxyRegionRegistersInterestForAllKeys() {
+ @SuppressWarnings("unchecked")
+ CacheListener<String, HttpSession>[] cacheListeners =
+ new CacheListener[] {new SessionExpirationCacheListener()};
+ doReturn(sessionRegion).when(cache).getRegion(sessionRegionName);
+ doReturn(attributes).when(sessionRegion).getAttributes();
+ doReturn(cacheListeners).when(attributes).getCacheListeners();
+ when(attributes.getDataPolicy()).thenReturn(DataPolicy.EMPTY);
+
+ sessionCache.initialize();
+
+ verify(sessionRegion).registerInterest("ALL_KEYS", InterestResultPolicy.KEYS);
+ }
+
+ @Test
+ public void touchSessionsInvokesPRFunctionForPRAndDoesNotThrowExceptionWhenFunctionDoesNotThrowException() {
+ Set<String> sessionIds = new HashSet<>();
+
+ when(sessionManager.getRegionAttributesId()).thenReturn(RegionShortcut.PARTITION.toString());
+
+ sessionCache.touchSessions(sessionIds);
+
+ verify(emptyExecution).execute(TouchPartitionedRegionEntriesFunction.ID);
+ }
+
+ @Test
+ public void touchSessionsInvokesPRFunctionForPRAndThrowsExceptionWhenFunctionThrowsException() {
+ Set<String> sessionIds = new HashSet<>();
+ FunctionException exception = new FunctionException();
+ ResultCollector exceptionCollector = mock(ResultCollector.class);
+
+ when(sessionManager.getRegionAttributesId()).thenReturn(RegionShortcut.PARTITION.toString());
+ when(emptyExecution.execute(TouchPartitionedRegionEntriesFunction.ID))
+ .thenReturn(exceptionCollector);
+ when(exceptionCollector.getResult()).thenThrow(exception);
+
+ sessionCache.touchSessions(sessionIds);
+ verify(logger).warn("Caught unexpected exception:", exception);
+ }
+
+ @Test
+ public void touchSessionsInvokesRRFunctionForRRAndDoesNotThrowExceptionWhenFunctionDoesNotThrowException() {
+ // Need to invoke this to set the session region
+ when(regionFactory.create(sessionRegionName)).thenReturn(sessionRegion);
+ sessionCache.initialize();
+
+ Set<String> sessionIds = new HashSet<>();
+
+ when(sessionRegion.getFullPath()).thenReturn("/" + sessionRegionName);
+ when(sessionManager.getRegionAttributesId()).thenReturn(RegionShortcut.REPLICATE.toString());
+
+ sessionCache.touchSessions(sessionIds);
+ verify(emptyExecution).execute(TouchReplicatedRegionEntriesFunction.ID);
+ }
+
+ @Test
+ public void touchSessionsInvokesRRFunctionForRRAndThrowsExceptionWhenFunctionThrowsException() {
+ // Need to invoke this to set the session region
+ when(regionFactory.create(sessionRegionName)).thenReturn(sessionRegion);
+ sessionCache.initialize();
+
+ Set<String> sessionIds = new HashSet<>();
+ FunctionException exception = new FunctionException();
+ ResultCollector exceptionCollector = mock(ResultCollector.class);
+
+ when(sessionRegion.getFullPath()).thenReturn("/" + sessionRegionName);
+ when(sessionManager.getRegionAttributesId()).thenReturn(RegionShortcut.REPLICATE.toString());
+ when(emptyExecution.execute(TouchReplicatedRegionEntriesFunction.ID))
+ .thenReturn(exceptionCollector);
+ when(exceptionCollector.getResult()).thenThrow(exception);
+
+ sessionCache.touchSessions(sessionIds);
+ verify(logger).warn("Caught unexpected exception:", exception);
+ }
+
+ @Test
+ public void isBackingCacheEnabledReturnsTrueWhenCommitValveFailfastDisabled() {
+ assertThat(sessionCache.isBackingCacheAvailable()).isTrue();
+ }
+
+ @Test
+ public void isBackingCacheEnabledReturnsValueWhenCommitValveFailfastEnabled() {
+ boolean backingCacheEnabled = false;
+ PoolImpl pool = mock(PoolImpl.class);
+
+ when(sessionManager.isCommitValveFailfastEnabled()).thenReturn(true);
+ doReturn(pool).when((ClientServerSessionCache) sessionCache).findPoolInPoolManager();
+ when(pool.isPrimaryUpdaterAlive()).thenReturn(backingCacheEnabled);
+
+ assertThat(sessionCache.isBackingCacheAvailable()).isEqualTo(backingCacheEnabled);
+ }
+}
diff --git a/extensions/geode-modules-test/src/main/java/org/apache/geode/modules/session/catalina/DeltaSessionFacadeJUnitTest.java b/extensions/geode-modules-test/src/main/java/org/apache/geode/modules/session/catalina/DeltaSessionFacadeJUnitTest.java
new file mode 100644
index 0000000..81254c7
--- /dev/null
+++ b/extensions/geode-modules-test/src/main/java/org/apache/geode/modules/session/catalina/DeltaSessionFacadeJUnitTest.java
@@ -0,0 +1,42 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more contributor license
+ * agreements. See the NOTICE file distributed with this work for additional information regarding
+ * copyright ownership. The ASF licenses this file to You 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.apache.geode.modules.session.catalina;
+
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+
+import org.junit.Test;
+
+public class DeltaSessionFacadeJUnitTest {
+
+ @Test
+ public void DeltaSessionFacadeMakesProperCallsOnSessionWhenInvoked() {
+ DeltaSessionInterface session = spy(new DeltaSession());
+
+ DeltaSessionFacade facade = new DeltaSessionFacade(session);
+
+ doNothing().when(session).commit();
+ doReturn(true).when(session).isValid();
+
+ facade.commit();
+ facade.isValid();
+
+ verify(session).commit();
+ verify(session).isValid();
+ }
+}
diff --git a/extensions/geode-modules-test/src/main/java/org/apache/geode/modules/session/catalina/DeltaSessionJUnitTest.java b/extensions/geode-modules-test/src/main/java/org/apache/geode/modules/session/catalina/DeltaSessionJUnitTest.java
new file mode 100644
index 0000000..1d55ce0
--- /dev/null
+++ b/extensions/geode-modules-test/src/main/java/org/apache/geode/modules/session/catalina/DeltaSessionJUnitTest.java
@@ -0,0 +1,205 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more contributor license
+ * agreements. See the NOTICE file distributed with this work for additional information regarding
+ * copyright ownership. The ASF licenses this file to You 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.apache.geode.modules.session.catalina;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.doThrow;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.List;
+
+import javax.servlet.http.HttpSession;
+
+import org.apache.catalina.Manager;
+import org.apache.catalina.session.StandardSession;
+import org.apache.juli.logging.Log;
+import org.junit.Before;
+import org.junit.Test;
+
+import org.apache.geode.cache.Region;
+import org.apache.geode.internal.util.BlobHelper;
+import org.apache.geode.modules.session.catalina.internal.DeltaSessionAttributeEvent;
+import org.apache.geode.modules.session.catalina.internal.DeltaSessionStatistics;
+
+public class DeltaSessionJUnitTest {
+
+ private DeltaSessionManager manager = mock(DeltaSessionManager.class);
+ private Region<String, HttpSession> sessionRegion = mock(Region.class);
+ private SessionCache sessionCache = mock(ClientServerSessionCache.class);
+ DeltaSessionStatistics stats = mock(DeltaSessionStatistics.class);
+ private final String sessionRegionName = "sessionRegionName";
+ private final String contextName = "contextName";
+ private Log logger = mock(Log.class);
+
+ @Before
+ public void setup() {
+ when(manager.getRegionName()).thenReturn(sessionRegionName);
+ when(manager.getSessionCache()).thenReturn(sessionCache);
+ when(manager.getLogger()).thenReturn(logger);
+ when(manager.getContextName()).thenReturn(contextName);
+ when(manager.getStatistics()).thenReturn(stats);
+ // For Client/Server behavior and some PeerToPeer use cases the session region and operating
+ // regions
+ // will be the same.
+ when(sessionCache.getOperatingRegion()).thenReturn(sessionRegion);
+ when(logger.isDebugEnabled()).thenReturn(true);
+ }
+
+ @Test
+ public void sessionConstructionThrowsIllegalArgumentExceptionIfProvidedManagerIsNotDeltaSessionManager() {
+ Manager invalidManager = mock(Manager.class);
+
+ assertThatThrownBy(() -> new DeltaSession(invalidManager))
+ .isInstanceOf(IllegalArgumentException.class)
+ .hasMessageContaining("The Manager must be an AbstractManager");
+ }
+
+ @Test
+ public void sessionConstructionDoesNotThrowExceptionWithValidArgument() {
+ DeltaSession session = new DeltaSession(manager);
+
+ verify(logger).debug(anyString());
+ }
+
+ @Test
+ public void getSessionCreatesFacadeWhenFacadeIsNullAndPackageProtectionDisabled() {
+ DeltaSession session = new DeltaSession(manager);
+
+ HttpSession returnedSession = session.getSession();
+
+ assertThat(returnedSession).isNotNull();
+ }
+
+ @Test
+ public void getSessionCreatesFacadeWhenFacadeIsNullAndPackageProtectionEnabled() {
+ DeltaSession session = spy(new DeltaSession(manager));
+ DeltaSessionFacade facade = mock(DeltaSessionFacade.class);
+ doReturn(true).when(session).isPackageProtectionEnabled();
+ doReturn(facade).when(session).getNewFacade(any(DeltaSession.class));
+
+ HttpSession returnedSession = session.getSession();
+
+ assertThat(returnedSession).isEqualTo(facade);
+ }
+
+ @Test
+ public void processExpiredIncrementsStatisticsCountForExpiredSessions() {
+ DeltaSession session = spy(new DeltaSession(manager));
+
+ doNothing().when((StandardSession) session).expire(false);
+ session.processExpired();
+
+ verify(stats).incSessionsExpired();
+ }
+
+ @Test
+ public void applyEventsAppliesEachEventAndPutsSessionIntoRegion() {
+ DeltaSessionAttributeEvent event1 = mock(DeltaSessionAttributeEvent.class);
+ DeltaSessionAttributeEvent event2 = mock(DeltaSessionAttributeEvent.class);
+ List<DeltaSessionAttributeEvent> events = new ArrayList<>();
+ events.add(event1);
+ events.add(event2);
+ Region<String, DeltaSessionInterface> region = mock(Region.class);
+ DeltaSession session = spy(new DeltaSession(manager));
+
+ session.applyAttributeEvents(region, events);
+
+ // confirm that events were all added to the queue
+ verify(session).addEventToEventQueue(event1);
+ verify(session).addEventToEventQueue(event2);
+
+ // confirm that session was put into region
+ verify(region).put(session.getId(), session, true);
+ }
+
+ @Test
+ public void commitThrowsIllegalStateExceptionWhenCalledOnInvalidSession() {
+ DeltaSession session = spy(new DeltaSession(manager));
+ String sessionId = "invalidatedSession";
+ doReturn(sessionId).when(session).getId();
+
+ assertThatThrownBy(() -> session.commit()).isInstanceOf(IllegalStateException.class)
+ .hasMessage("commit: Session " + sessionId + " already invalidated");
+ }
+
+ @Test
+ public void getSizeInBytesReturnsProperValueForMultipleAttributes() {
+ String attrName1 = "attrName1";
+ String attrName2 = "attrName2";
+ List attrList = new ArrayList<String>();
+ attrList.add(attrName1);
+ attrList.add(attrName2);
+
+ Enumeration<String> attrNames = Collections.enumeration(attrList);
+
+ byte[] value1 = {0, 0, 0, 0};
+ byte[] value2 = {0, 0, 0, 0, 0};
+ int totalSize = value1.length + value2.length;
+
+ DeltaSession session = spy(new DeltaSession(manager));
+ doReturn(attrNames).when(session).getAttributeNames();
+ doReturn(value1).when(session).getAttributeWithoutDeserialize(attrName1);
+ doReturn(value2).when(session).getAttributeWithoutDeserialize(attrName2);
+
+ int sessionSize = session.getSizeInBytes();
+
+ assertThat(sessionSize).isEqualTo(totalSize);
+ }
+
+ @Test
+ public void serializeLogsWarningWhenExceptionIsThrownDuringSerialization() throws IOException {
+ Object obj = "unserialized object";
+ String exceptionMessaage = "Serialization failed.";
+ IOException exception = new IOException(exceptionMessaage);
+
+ DeltaSession session = spy(new DeltaSession(manager));
+ doThrow(exception).when(session).serializeViaBlobHelper(obj);
+ session.serialize(obj);
+
+ verify(logger).warn(anyString(), any(IOException.class));
+ }
+
+ @Test
+ public void serializeReturnsSerializedObject() throws IOException {
+ Object obj = "unserialized object";
+ byte[] serializedObj = BlobHelper.serializeToBlob(obj);
+
+ DeltaSession session = spy(new DeltaSession(manager));
+ byte[] result = session.serialize(obj);
+
+ assertThat(result).isEqualTo(serializedObj);
+ }
+
+ // @Test
+ // public void testToData() throws IOException {
+ // DeltaSession session = spy(new DeltaSession(manager));
+ // DataOutput out = mock(DataOutput.class);
+ //
+ // session.toData(out);
+ // }
+}
diff --git a/extensions/geode-modules-test/src/main/java/org/apache/geode/modules/session/catalina/DeltaSessionManagerJUnitTest.java b/extensions/geode-modules-test/src/main/java/org/apache/geode/modules/session/catalina/DeltaSessionManagerJUnitTest.java
new file mode 100644
index 0000000..fec8571
--- /dev/null
+++ b/extensions/geode-modules-test/src/main/java/org/apache/geode/modules/session/catalina/DeltaSessionManagerJUnitTest.java
@@ -0,0 +1,471 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more contributor license
+ * agreements. See the NOTICE file distributed with this work for additional information regarding
+ * copyright ownership. The ASF licenses this file to You 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.apache.geode.modules.session.catalina;
+
+import static org.apache.geode.modules.util.RegionConfiguration.DEFAULT_MAX_INACTIVE_INTERVAL;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.doReturn;
+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 static org.mockito.Mockito.when;
+import static org.mockito.Mockito.withSettings;
+
+import java.beans.PropertyChangeEvent;
+import java.io.BufferedInputStream;
+import java.io.BufferedOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.util.HashSet;
+import java.util.Set;
+
+import javax.servlet.http.HttpSession;
+
+import org.apache.catalina.Context;
+import org.apache.catalina.Loader;
+import org.apache.catalina.Session;
+import org.apache.catalina.session.StandardSession;
+import org.apache.juli.logging.Log;
+import org.junit.Test;
+
+import org.apache.geode.cache.Cache;
+import org.apache.geode.cache.Region;
+import org.apache.geode.cache.query.FunctionDomainException;
+import org.apache.geode.cache.query.NameResolutionException;
+import org.apache.geode.cache.query.Query;
+import org.apache.geode.cache.query.QueryInvocationTargetException;
+import org.apache.geode.cache.query.SelectResults;
+import org.apache.geode.cache.query.TypeMismatchException;
+import org.apache.geode.cache.query.internal.InternalQueryService;
+import org.apache.geode.cache.query.internal.LinkedResultSet;
+import org.apache.geode.internal.cache.GemFireCacheImpl;
+import org.apache.geode.modules.session.catalina.internal.DeltaSessionStatistics;
+
+public abstract class DeltaSessionManagerJUnitTest {
+
+ protected DeltaSessionManager manager;
+ protected AbstractSessionCache sessionCache;
+ protected Cache cache;
+ protected Log logger;
+ protected Context context;
+ protected DeltaSessionStatistics managerStats;
+ protected DeltaSessionStatistics cacheStats;
+ protected Region<String, HttpSession> operatingRegion;
+
+ public void initTest() {
+ sessionCache = mock(AbstractSessionCache.class);
+ cache = mock(GemFireCacheImpl.class);
+ logger = mock(Log.class);
+ context = mock(Context.class);
+ managerStats = mock(DeltaSessionStatistics.class);
+ cacheStats = mock(DeltaSessionStatistics.class);
+ operatingRegion = mock(Region.class);
+
+ doReturn(sessionCache).when(manager).getSessionCache();
+ doReturn(logger).when(manager).getLogger();
+ doReturn(context).when(manager).getTheContext();
+ doReturn(managerStats).when(manager).getStatistics();
+ doReturn(cacheStats).when(sessionCache).getStatistics();
+ doReturn(operatingRegion).when(sessionCache).getOperatingRegion();
+ }
+
+ @Test
+ public void getRegionAttributesIdSetsIdFromSessionCacheWhenAttributesIdIsNull() {
+ String regionAttributesId = "attributesIdFromSessionCache";
+
+ doReturn(regionAttributesId).when(sessionCache).getDefaultRegionAttributesId();
+ String attrId = manager.getRegionAttributesId();
+
+ verify(sessionCache).getDefaultRegionAttributesId();
+ assertThat(attrId).isEqualTo(regionAttributesId);
+ }
+
+ @Test
+ public void getEnableLocalCacheSetsIdFromSessionCacheWhenEnableLocalCacheIsNull() {
+ boolean isLocalCacheEnabled = true;
+
+ doReturn(isLocalCacheEnabled).when(sessionCache).getDefaultEnableLocalCache();
+ Boolean localCacheEnabledValue = manager.getEnableLocalCache();
+
+ verify(sessionCache).getDefaultEnableLocalCache();
+ assertThat(localCacheEnabledValue).isEqualTo(isLocalCacheEnabled);
+ }
+
+ @Test
+ public void findSessionsReturnsNullWhenIdIsNull() throws IOException {
+ Session session = manager.findSession(null);
+
+ assertThat(session).isNull();
+ }
+
+ @Test
+ public void findSessionsReturnsNullAndLogsMessageWhenContextNameIsNotValid() throws IOException {
+ String sessionId = "sessionId";
+ String contextName = "contextName";
+ String invalidContextName = "invalidContextName";
+
+ DeltaSession expectedSession = mock(DeltaSession.class);
+ when(sessionCache.getSession(sessionId)).thenReturn(expectedSession);
+ when(expectedSession.getContextName()).thenReturn(invalidContextName);
+ when(context.getName()).thenReturn(contextName);
+
+ Session session = manager.findSession(sessionId);
+
+ verify(logger).info(anyString());
+ assertThat(session).isNull();
+ }
+
+ @Test
+ public void findSessionsReturnsNullWhenIdIsNotFound() throws IOException {
+ String sessionId = "sessionId";
+
+ when(sessionCache.getSession(sessionId)).thenReturn(null);
+
+ Session session = manager.findSession(sessionId);
+
+ assertThat(session).isNull();
+ }
+
+ @Test
+ public void findSessionsReturnsProperSessionByIdWhenIdAndContextNameIsValid() throws IOException {
+ String sessionId = "sessionId";
+ String contextName = "contextName";
+
+ DeltaSession expectedSession = mock(DeltaSession.class);
+ when(sessionCache.getSession(sessionId)).thenReturn(expectedSession);
+ when(expectedSession.getContextName()).thenReturn(contextName);
+ when(context.getName()).thenReturn(contextName);
+
+ Session session = manager.findSession(sessionId);
+
+ assertThat(session).isEqualTo(expectedSession);
+ }
+
+ @Test
+ public void removeProperlyDestroysSessionFromSessionCacheWhenSessionIsNotExpired() {
+ DeltaSession sessionToDestroy = mock(DeltaSession.class);
+ String sessionId = "sessionId";
+
+ when(sessionToDestroy.getId()).thenReturn(sessionId);
+ when(sessionToDestroy.getExpired()).thenReturn(false);
+
+ manager.remove(sessionToDestroy);
+
+ verify(sessionCache).destroySession(sessionId);
+ }
+
+ @Test
+ public void removeDoesNotDestroySessionFromSessionCacheWhenSessionIsExpired() {
+ DeltaSession sessionToDestroy = mock(DeltaSession.class);
+ String sessionId = "sessionId";
+
+ when(sessionToDestroy.getId()).thenReturn(sessionId);
+ when(sessionToDestroy.getExpired()).thenReturn(true);
+
+ manager.remove(sessionToDestroy);
+
+ verify(sessionCache, times(0)).destroySession(sessionId);
+ }
+
+ @Test
+ public void addPutsSessionIntoSessionCacheAndIncrementsStats() {
+ DeltaSession sessionToPut = mock(DeltaSession.class);
+
+ manager.add(sessionToPut);
+
+ verify(sessionCache).putSession(sessionToPut);
+ verify(cacheStats).incSessionsCreated();
+ }
+
+ @Test
+ public void listIdsListsAllPresentIds() {
+ Set<String> ids = new HashSet<>();
+ ids.add("id1");
+ ids.add("id2");
+ ids.add("id3");
+
+ when(sessionCache.keySet()).thenReturn(ids);
+
+ String listOutput = manager.listSessionIds();
+
+ for (String id : ids) {
+ assertThat(listOutput).contains(id);
+ }
+ }
+
+ @Test
+ public void loadActivatesAndAddsSingleSessionWithValidIdAndMoreRecentAccessTime()
+ throws IOException, ClassNotFoundException {
+ String contextPath = "contextPath";
+ String expectedStoreDir = "";
+ DeltaSession newSession = mock(DeltaSession.class);
+ DeltaSession existingSession = mock(DeltaSession.class);
+
+ prepareMocksForLoadTest(contextPath, newSession, existingSession, expectedStoreDir);
+
+ manager.load();
+
+ verify(newSession).activate();
+ verify(manager).add(newSession);
+ }
+
+ @Test
+ public void loadLogsWarningAndDoesNotAddSessionWhenSessionStoreNotFound()
+ throws IOException, ClassNotFoundException {
+ String contextPath = "contextPath";
+ String expectedStoreDir = "";
+ DeltaSession newSession = mock(DeltaSession.class);
+ DeltaSession existingSession = mock(DeltaSession.class);
+
+ prepareMocksForLoadTest(contextPath, newSession, existingSession, expectedStoreDir);
+
+ doReturn(null).when(manager).getFileAtPath(any(), any());
+
+ manager.load();
+
+ verify(logger).debug("No session store file found");
+ verify(manager, times(0)).add(any());
+ }
+
+ @Test
+ public void loadDoesNotAddSessionToManagerWithValidIdAndLessRecentAccessTime()
+ throws IOException, ClassNotFoundException {
+ String contextPath = "contextPath";
+ String expectedStoreDir = "";
+ DeltaSession newSession = mock(DeltaSession.class);
+ DeltaSession existingSession = mock(DeltaSession.class);
+
+ prepareMocksForLoadTest(contextPath, newSession, existingSession, expectedStoreDir);
+
+ when(existingSession.getLastAccessedTime()).thenReturn(2L);
+
+ manager.load();
+
+ verify(newSession, times(0)).activate();
+ verify(manager, times(0)).add(newSession);
+ }
+
+ @Test
+ public void unloadWritesSingleSessionToDiskWhenIdIsValid()
+ throws IOException, NameResolutionException, TypeMismatchException,
+ QueryInvocationTargetException, FunctionDomainException {
+ String sessionId = "sessionId";
+ DeltaSession session = mock(DeltaSession.class);
+ FileOutputStream fos = mock(FileOutputStream.class);
+ BufferedOutputStream bos = mock(BufferedOutputStream.class);
+ ObjectOutputStream oos = mock(ObjectOutputStream.class);
+
+ prepareMocksForUnloadTest(sessionId, fos, bos, oos, session);
+
+ manager.unload();
+
+ verify((StandardSession) session).writeObjectData(oos);
+ }
+
+ @Test
+ public void unloadDoesNotWriteSessionToDiskAndClosesOutputStreamsWhenOutputStreamThrowsIOException()
+ throws IOException, NameResolutionException, TypeMismatchException,
+ QueryInvocationTargetException, FunctionDomainException {
+ String sessionId = "sessionId";
+ DeltaSession session = mock(DeltaSession.class);
+ FileOutputStream fos = mock(FileOutputStream.class);
+ BufferedOutputStream bos = mock(BufferedOutputStream.class);
+ ObjectOutputStream oos = mock(ObjectOutputStream.class);
+
+ prepareMocksForUnloadTest(sessionId, fos, bos, oos, session);
+
+ String exceptionMessage = "Output Stream IOException";
+
+ IOException exception = new IOException(exceptionMessage);
+
+ doThrow(exception).when(manager).getObjectOutputStream(bos);
+
+ assertThatThrownBy(() -> manager.unload()).isInstanceOf(IOException.class)
+ .hasMessage(exceptionMessage);
+
+ verify((StandardSession) session, times(0)).writeObjectData(oos);
+ verify(bos).close();
+ verify(fos).close();
+ }
+
+ @Test
+ public void unloadDoesNotWriteSessionToDiskAndClosesOutputStreamsWhenSessionIsWrongClass()
+ throws IOException, NameResolutionException, TypeMismatchException,
+ QueryInvocationTargetException, FunctionDomainException {
+ String sessionId = "sessionId";
+ DeltaSession session = mock(DeltaSession.class);
+ FileOutputStream fos = mock(FileOutputStream.class);
+ BufferedOutputStream bos = mock(BufferedOutputStream.class);
+ ObjectOutputStream oos = mock(ObjectOutputStream.class);
+
+ prepareMocksForUnloadTest(sessionId, fos, bos, oos, session);
+
+ Session invalidSession =
+ mock(Session.class, withSettings().extraInterfaces(DeltaSessionInterface.class));
+
+ doReturn(invalidSession).when(manager).findSession(sessionId);
+
+ assertThatThrownBy(() -> manager.unload()).isInstanceOf(IOException.class);
+
+ verify((StandardSession) session, times(0)).writeObjectData(oos);
+ verify(oos).close();
+ }
+
+ @Test
+ public void successfulUnloadWithClientServerSessionCachePerformsLocalDestroy()
+ throws IOException, NameResolutionException, TypeMismatchException,
+ QueryInvocationTargetException, FunctionDomainException {
+ String sessionId = "sessionId";
+ DeltaSession session = mock(DeltaSession.class);
+ FileOutputStream fos = mock(FileOutputStream.class);
+ BufferedOutputStream bos = mock(BufferedOutputStream.class);
+ ObjectOutputStream oos = mock(ObjectOutputStream.class);
+
+ prepareMocksForUnloadTest(sessionId, fos, bos, oos, session);
+
+ when(sessionCache.isClientServer()).thenReturn(true);
+ when(session.getId()).thenReturn(sessionId);
+
+ manager.unload();
+
+ verify((StandardSession) session).writeObjectData(oos);
+ verify(operatingRegion).localDestroy(sessionId);
+ }
+
+ @Test
+ public void propertyChangeSetsMaxInactiveIntervalWithCorrectPropertyNameAndValue() {
+ String propertyName = "sessionTimeout";
+ PropertyChangeEvent event = mock(PropertyChangeEvent.class);
+ Context eventContext = mock(Context.class);
+ Integer newValue = 1;
+
+ when(event.getSource()).thenReturn(eventContext);
+ when(event.getPropertyName()).thenReturn(propertyName);
+ when(event.getNewValue()).thenReturn(newValue);
+
+ manager.propertyChange(event);
+
+ verify(manager).setMaxInactiveInterval(newValue * 60);
+ }
+
+ @Test
+ public void propertyChangeDoesNotSetMaxInactiveIntervalWithIncorrectPropertyName() {
+ String propertyName = "wrong name";
+ PropertyChangeEvent event = mock(PropertyChangeEvent.class);
+ Context eventContext = mock(Context.class);
+
+ when(event.getSource()).thenReturn(eventContext);
+ when(event.getPropertyName()).thenReturn(propertyName);
+
+ manager.propertyChange(event);
+
+ verify(manager, times(0)).setMaxInactiveInterval(anyInt());
+ }
+
+ @Test
+ public void propertyChangeDoesNotSetNewMaxInactiveIntervalWithCorrectPropertyNameAndInvalidPropertyValue() {
+ String propertyName = "sessionTimeout";
+ PropertyChangeEvent event = mock(PropertyChangeEvent.class);
+ Context eventContext = mock(Context.class);
+ Integer newValue = -2;
+ Integer oldValue = DEFAULT_MAX_INACTIVE_INTERVAL;
+
+ when(event.getSource()).thenReturn(eventContext);
+ when(event.getPropertyName()).thenReturn(propertyName);
+ when(event.getNewValue()).thenReturn(newValue);
+ when(event.getOldValue()).thenReturn(oldValue);
+
+ manager.propertyChange(event);
+
+ verify(manager).setMaxInactiveInterval(oldValue);
+ }
+
+ public void prepareMocksForUnloadTest(String sessionId, FileOutputStream fos,
+ BufferedOutputStream bos, ObjectOutputStream oos, DeltaSession session)
+ throws NameResolutionException, TypeMismatchException, QueryInvocationTargetException,
+ FunctionDomainException, IOException {
+ String regionName = "regionName";
+ String contextPath = "contextPath";
+ String catalinaBaseSystemProp = "Catalina/Base";
+ String systemFileSeparator = "/";
+ String expectedStoreDir = catalinaBaseSystemProp + systemFileSeparator + "temp";
+
+ InternalQueryService queryService = mock(InternalQueryService.class);
+ Query query = mock(Query.class);
+ File store = mock(File.class);
+ SelectResults results = new LinkedResultSet();
+
+ when(sessionCache.getCache()).thenReturn(cache);
+ when(context.getPath()).thenReturn(contextPath);
+ when(cache.getQueryService()).thenReturn(queryService);
+ when(queryService.newQuery(anyString())).thenReturn(query);
+ when(query.execute()).thenReturn(results);
+ doReturn(catalinaBaseSystemProp).when(manager)
+ .getSystemPropertyValue(DeltaSessionManager.catalinaBaseSystemProperty);
+ doReturn(systemFileSeparator).when(manager)
+ .getSystemPropertyValue(DeltaSessionManager.fileSeparatorSystemProperty);
+ doReturn(store).when(manager).getFileAtPath(expectedStoreDir, contextPath);
+ doReturn(fos).when(manager).getFileOutputStream(store);
+ doReturn(bos).when(manager).getBufferedOutputStream(fos);
+ doReturn(oos).when(manager).getObjectOutputStream(bos);
+ doReturn(regionName).when(manager).getRegionName();
+ doReturn(session).when(manager).findSession(sessionId);
+ doNothing().when(manager).writeToObjectOutputStream(any(), any());
+
+ results.add(sessionId);
+ }
+
+ public void prepareMocksForLoadTest(String contextPath, DeltaSession newSession,
+ DeltaSession existingSession, String expectedStoreDir)
+ throws IOException, ClassNotFoundException {
+ String catalinaBaseSystemProp = "Catalina/Base";
+ String systemFileSeparator = "/";
+ expectedStoreDir = catalinaBaseSystemProp + systemFileSeparator + "temp";
+ String newSessionId = "newSessionId";
+
+ File store = mock(File.class);
+ FileInputStream fis = mock(FileInputStream.class);
+ BufferedInputStream bis = mock(BufferedInputStream.class);
+ ObjectInputStream ois = mock(ObjectInputStream.class);
+ Loader loader = mock(Loader.class);
+
+ when(context.getPath()).thenReturn(contextPath);
+ when(context.getLoader()).thenReturn(loader);
+ when(newSession.getId()).thenReturn(newSessionId);
+ when(newSession.getLastAccessedTime()).thenReturn(1L);
+ when(newSession.isValid()).thenReturn(true);
+ when(existingSession.getLastAccessedTime()).thenReturn(0L);
+ doReturn(catalinaBaseSystemProp).when(manager).getSystemPropertyValue("catalina.base");
+ doReturn(systemFileSeparator).when(manager).getSystemPropertyValue("file.separator");
+ doReturn(store).when(manager).getFileAtPath(expectedStoreDir, contextPath);
+ doReturn(fis).when(manager).getFileInputStream(store);
+ doReturn(bis).when(manager).getBufferedInputStream(fis);
+ doReturn(ois).when(manager).getObjectInputStream(bis);
+ doReturn(1).when(manager).getSessionCountFromObjectInputStream(ois);
+ doReturn(newSession).when(manager).getNewSession();
+ doReturn(existingSession).when(operatingRegion).get(newSessionId);
+ }
+}
diff --git a/extensions/geode-modules-test/src/main/java/org/apache/geode/modules/session/catalina/PeerToPeerSessionCacheJUnitTest.java b/extensions/geode-modules-test/src/main/java/org/apache/geode/modules/session/catalina/PeerToPeerSessionCacheJUnitTest.java
new file mode 100644
index 0000000..2bea8de
--- /dev/null
+++ b/extensions/geode-modules-test/src/main/java/org/apache/geode/modules/session/catalina/PeerToPeerSessionCacheJUnitTest.java
@@ -0,0 +1,204 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more contributor license
+ * agreements. See the NOTICE file distributed with this work for additional information regarding
+ * copyright ownership. The ASF licenses this file to You 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.apache.geode.modules.session.catalina;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.doThrow;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import javax.servlet.http.HttpSession;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import org.apache.geode.cache.Cache;
+import org.apache.geode.cache.Region;
+import org.apache.geode.cache.RegionFactory;
+import org.apache.geode.cache.RegionShortcut;
+import org.apache.geode.cache.execute.FunctionException;
+import org.apache.geode.cache.execute.ResultCollector;
+import org.apache.geode.modules.session.catalina.callback.SessionExpirationCacheListener;
+import org.apache.geode.modules.util.RegionConfiguration;
+import org.apache.geode.modules.util.SessionCustomExpiry;
+import org.apache.geode.modules.util.TouchPartitionedRegionEntriesFunction;
+import org.apache.geode.modules.util.TouchReplicatedRegionEntriesFunction;
+
+public class PeerToPeerSessionCacheJUnitTest extends AbstractSessionCacheJUnitTest {
+
+ private String localRegionName = sessionRegionName + "_local";
+ @SuppressWarnings("unchecked")
+ private RegionFactory<String, HttpSession> regionFactory = mock(RegionFactory.class);
+ @SuppressWarnings("unchecked")
+ private Region<String, HttpSession> localRegion = mock(Region.class);
+ private Cache cache = mock(Cache.class);
+
+ @Before
+ public void setUp() {
+ sessionCache = spy(new PeerToPeerSessionCache(sessionManager, cache));
+ doReturn(sessionRegion).when((PeerToPeerSessionCache) sessionCache)
+ .createRegionUsingHelper(any(RegionConfiguration.class));
+ doReturn(true).when((PeerToPeerSessionCache) sessionCache)
+ .isFunctionRegistered(any(String.class));
+
+ when(sessionManager.getRegionName()).thenReturn(sessionRegionName);
+ when(sessionManager.getRegionAttributesId()).thenReturn(RegionShortcut.PARTITION.toString());
+ when(sessionManager.getLogger()).thenReturn(logger);
+ when(sessionManager.getEnableLocalCache()).thenReturn(true);
+ when(sessionManager.getMaxInactiveInterval())
+ .thenReturn(RegionConfiguration.DEFAULT_MAX_INACTIVE_INTERVAL);
+
+ when(sessionRegion.getName()).thenReturn(sessionRegionName);
+
+ doReturn(regionFactory).when(cache).createRegionFactory(RegionShortcut.LOCAL_HEAP_LRU);
+ when(regionFactory.create(localRegionName)).thenReturn(localRegion);
+
+ when(cache.getDistributedSystem()).thenReturn(distributedSystem);
+ }
+
+ @Test
+ public void initializeSessionCacheSucceeds() {
+ sessionCache.initialize();
+
+ verify(cache).createRegionFactory(RegionShortcut.LOCAL_HEAP_LRU);
+ verify(regionFactory).create(localRegionName);
+ verify((PeerToPeerSessionCache) sessionCache)
+ .createRegionUsingHelper(any(RegionConfiguration.class));
+ verify(regionFactory, times(0)).setStatisticsEnabled(true);
+ verify(regionFactory, times(0)).setCustomEntryIdleTimeout(any(SessionCustomExpiry.class));
+ verify(regionFactory, times(0)).addCacheListener(any(SessionExpirationCacheListener.class));
+ }
+
+ @Test
+ public void functionRegistrationDoesNotThrowException() {
+ doReturn(false).when((PeerToPeerSessionCache) sessionCache)
+ .isFunctionRegistered(any(String.class));
+
+ sessionCache.initialize();
+
+ verify((PeerToPeerSessionCache) sessionCache).registerFunctionWithFunctionService(any(
+ TouchPartitionedRegionEntriesFunction.class));
+ verify((PeerToPeerSessionCache) sessionCache).registerFunctionWithFunctionService(any(
+ TouchReplicatedRegionEntriesFunction.class));
+ }
+
+ @Test
+ public void initializeSessionCacheSucceedsWhenSessionRegionAlreadyExists() {
+ doReturn(sessionRegion).when(cache).getRegion(sessionRegionName);
+ doNothing().when((PeerToPeerSessionCache) sessionCache)
+ .validateRegionUsingRegionhelper(any(RegionConfiguration.class), any(Region.class));
+
+ sessionCache.initialize();
+
+ verify((PeerToPeerSessionCache) sessionCache, times(0))
+ .createRegionUsingHelper(any(RegionConfiguration.class));
+ }
+
+ @Test
+ public void nonDefaultMaxTimeoutIntervalSetsExpirationDetails() {
+ // Setting the mocked return value of getMaxInactiveInterval to something distinctly not equal
+ // to the default
+ when(sessionManager.getMaxInactiveInterval())
+ .thenReturn(RegionConfiguration.DEFAULT_MAX_INACTIVE_INTERVAL + 1);
+
+ sessionCache.initialize();
+
+ verify(regionFactory).setStatisticsEnabled(true);
+ verify(regionFactory).setCustomEntryIdleTimeout(any(SessionCustomExpiry.class));
+ verify(regionFactory).addCacheListener(any(SessionExpirationCacheListener.class));
+ }
+
+ @Test
+ public void initializeSessionCacheSucceedsWhenLocalRegionAlreadyExists() {
+ doReturn(localRegion).when(cache).getRegion(localRegionName);
+
+ sessionCache.initialize();
+
+ verify(regionFactory, times(0)).create(any(String.class));
+ }
+
+
+ @Test
+ public void operationRegionIsCorrectlySetWhenEnableLocalCachingIsFalse() {
+ when(sessionManager.getEnableLocalCache()).thenReturn(false);
+
+ sessionCache.initialize();
+
+ verify(cache, times(0)).getRegion(localRegionName);
+ assertThat(sessionCache.sessionRegion).isEqualTo(sessionCache.operatingRegion);
+ }
+
+ @Test
+ public void touchSessionsWithPartitionedRegionSucceeds() {
+ Set<String> sessionIds = new HashSet<>();
+ ResultCollector collector = mock(ResultCollector.class);
+
+ when(sessionManager.getRegionAttributesId()).thenReturn(RegionShortcut.PARTITION.toString());
+ doReturn(emptyExecution).when((PeerToPeerSessionCache) sessionCache)
+ .getExecutionForFunctionOnRegionWithFilter(sessionIds);
+ when(emptyExecution.execute(TouchPartitionedRegionEntriesFunction.ID)).thenReturn(collector);
+
+ sessionCache.touchSessions(sessionIds);
+
+ verify(emptyExecution).execute(TouchPartitionedRegionEntriesFunction.ID);
+ verify(collector).getResult();
+ }
+
+ @Test
+ public void touchSessionsWithReplicatedRegionSucceeds() {
+ // Need to invoke this to set the session region
+ sessionCache.initialize();
+
+ Set<String> sessionIds = new HashSet<>();
+ ResultCollector collector = mock(ResultCollector.class);
+
+ when(sessionManager.getRegionAttributesId()).thenReturn(RegionShortcut.REPLICATE.toString());
+ doReturn(emptyExecution).when((PeerToPeerSessionCache) sessionCache)
+ .getExecutionForFunctionOnMembersWithArguments(any(Object[].class));
+ when(emptyExecution.execute(TouchReplicatedRegionEntriesFunction.ID)).thenReturn(collector);
+
+ sessionCache.touchSessions(sessionIds);
+
+ verify(emptyExecution).execute(TouchReplicatedRegionEntriesFunction.ID);
+ verify(collector).getResult();
+ }
+
+ @Test
+ public void touchSessionsCatchesThrownException() {
+ Set<String> sessionIds = new HashSet<>();
+ ResultCollector collector = mock(ResultCollector.class);
+ FunctionException exception = new FunctionException();
+
+ when(sessionManager.getRegionAttributesId()).thenReturn(RegionShortcut.PARTITION.toString());
+ doReturn(emptyExecution).when((PeerToPeerSessionCache) sessionCache)
+ .getExecutionForFunctionOnRegionWithFilter(sessionIds);
+ when(emptyExecution.execute(TouchPartitionedRegionEntriesFunction.ID)).thenReturn(collector);
+ doThrow(exception).when(collector).getResult();
+
+ sessionCache.touchSessions(sessionIds);
+
+ verify(logger).warn("Caught unexpected exception:", exception);
+ }
+}
diff --git a/extensions/geode-modules-test/src/main/java/org/apache/geode/modules/session/catalina/callback/SessionExpirationCacheListenerJUnitTest.java b/extensions/geode-modules-test/src/main/java/org/apache/geode/modules/session/catalina/callback/SessionExpirationCacheListenerJUnitTest.java
new file mode 100644
index 0000000..7228fe8
--- /dev/null
+++ b/extensions/geode-modules-test/src/main/java/org/apache/geode/modules/session/catalina/callback/SessionExpirationCacheListenerJUnitTest.java
@@ -0,0 +1,44 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more contributor license
+ * agreements. See the NOTICE file distributed with this work for additional information regarding
+ * copyright ownership. The ASF licenses this file to You 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.apache.geode.modules.session.catalina.callback;
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import javax.servlet.http.HttpSession;
+
+import org.junit.Test;
+
+import org.apache.geode.cache.EntryEvent;
+import org.apache.geode.cache.Operation;
+import org.apache.geode.modules.session.catalina.DeltaSession;
+
+public class SessionExpirationCacheListenerJUnitTest {
+ @Test
+ public void TestAfterDestroyProcessesSessionExpiredByGemfire() {
+ SessionExpirationCacheListener listener = new SessionExpirationCacheListener();
+ EntryEvent<String, HttpSession> event = mock(EntryEvent.class);
+ DeltaSession session = mock(DeltaSession.class);
+
+ when(event.getOperation()).thenReturn(Operation.EXPIRE_DESTROY);
+ when(event.getOldValue()).thenReturn(session);
+
+ listener.afterDestroy(event);
+
+ verify(session).processExpired();
+ }
+}
diff --git a/extensions/geode-modules-test/src/main/java/org/apache/geode/modules/session/catalina/internal/DeltaSessionAttributeEventBatchJUnitTest.java b/extensions/geode-modules-test/src/main/java/org/apache/geode/modules/session/catalina/internal/DeltaSessionAttributeEventBatchJUnitTest.java
new file mode 100644
index 0000000..bee73b8
--- /dev/null
+++ b/extensions/geode-modules-test/src/main/java/org/apache/geode/modules/session/catalina/internal/DeltaSessionAttributeEventBatchJUnitTest.java
@@ -0,0 +1,64 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more contributor license
+ * agreements. See the NOTICE file distributed with this work for additional information regarding
+ * copyright ownership. The ASF licenses this file to You 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.apache.geode.modules.session.catalina.internal;
+
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.junit.Test;
+
+import org.apache.geode.LogWriter;
+import org.apache.geode.cache.Cache;
+import org.apache.geode.cache.Region;
+import org.apache.geode.modules.session.catalina.DeltaSessionInterface;
+
+public class DeltaSessionAttributeEventBatchJUnitTest {
+ String regionName = "regionName";
+ String sessionId = "sessionId";
+ LogWriter logWriter = mock(LogWriter.class);
+
+ @Test
+ public void TestApplyForBatch() {
+
+ List<DeltaSessionAttributeEvent> eventList = new ArrayList<>();
+ DeltaSessionAttributeEvent event1 = mock(DeltaSessionAttributeEvent.class);
+ DeltaSessionAttributeEvent event2 = mock(DeltaSessionAttributeEvent.class);
+ eventList.add(event1);
+ eventList.add(event2);
+
+
+ Cache cache = mock(Cache.class);
+ Region<String, DeltaSessionInterface> region = mock(Region.class);
+ DeltaSessionInterface deltaSessionInterface = mock(DeltaSessionInterface.class);
+
+ doReturn(region).when(cache).getRegion(regionName);
+ when(cache.getLogger()).thenReturn(logWriter);
+ when(logWriter.fineEnabled()).thenReturn(false);
+ when(region.get(sessionId)).thenReturn(deltaSessionInterface);
+
+ DeltaSessionAttributeEventBatch batch =
+ new DeltaSessionAttributeEventBatch(regionName, sessionId, eventList);
+
+ batch.apply(cache);
+
+ verify(deltaSessionInterface).applyAttributeEvents(region, eventList);
+ }
+}
diff --git a/extensions/geode-modules-test/src/main/java/org/apache/geode/modules/session/catalina/internal/DeltaSessionDestroyAttributeEventJUnitTest.java b/extensions/geode-modules-test/src/main/java/org/apache/geode/modules/session/catalina/internal/DeltaSessionDestroyAttributeEventJUnitTest.java
new file mode 100644
index 0000000..5ea2648
--- /dev/null
+++ b/extensions/geode-modules-test/src/main/java/org/apache/geode/modules/session/catalina/internal/DeltaSessionDestroyAttributeEventJUnitTest.java
@@ -0,0 +1,36 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more contributor license
+ * agreements. See the NOTICE file distributed with this work for additional information regarding
+ * copyright ownership. The ASF licenses this file to You 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.apache.geode.modules.session.catalina.internal;
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+
+import org.junit.Test;
+
+import org.apache.geode.modules.session.catalina.DeltaSessionInterface;
+
+public class DeltaSessionDestroyAttributeEventJUnitTest {
+ @Test
+ public void DeltaSessionDestroyAttributeEventAppliesAttributeToSession() {
+ String attributeName = "DestroyAttribute";
+
+ DeltaSessionDestroyAttributeEvent event = new DeltaSessionDestroyAttributeEvent(attributeName);
+ DeltaSessionInterface deltaSessionInterface = mock(DeltaSessionInterface.class);
+ event.apply((deltaSessionInterface));
+
+ verify(deltaSessionInterface).localDestroyAttribute(attributeName);
+ }
+}
diff --git a/extensions/geode-modules-test/src/main/java/org/apache/geode/modules/session/catalina/internal/DeltaSessionStatisticsJUnitTest.java b/extensions/geode-modules-test/src/main/java/org/apache/geode/modules/session/catalina/internal/DeltaSessionStatisticsJUnitTest.java
new file mode 100644
index 0000000..51b8129
--- /dev/null
+++ b/extensions/geode-modules-test/src/main/java/org/apache/geode/modules/session/catalina/internal/DeltaSessionStatisticsJUnitTest.java
@@ -0,0 +1,56 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more contributor license
+ * agreements. See the NOTICE file distributed with this work for additional information regarding
+ * copyright ownership. The ASF licenses this file to You 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.apache.geode.modules.session.catalina.internal;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.anyLong;
+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 org.junit.Test;
+
+import org.apache.geode.Statistics;
+import org.apache.geode.distributed.internal.InternalDistributedSystem;
+
+public class DeltaSessionStatisticsJUnitTest {
+
+ @Test
+ public void CreatedDeltaSessionStatisticsAccessProperStats() {
+ String appName = "DeltaSessionStatisticsTest";
+
+ InternalDistributedSystem internalDistributedSystem = mock(InternalDistributedSystem.class);
+ Statistics statistics = mock(Statistics.class);
+
+ when(internalDistributedSystem.createAtomicStatistics(any(), any())).thenReturn(statistics);
+
+ DeltaSessionStatistics deltaSessionStatistics =
+ new DeltaSessionStatistics(internalDistributedSystem, appName);
+
+ deltaSessionStatistics.incSessionsCreated();
+ deltaSessionStatistics.incSessionsExpired();
+ deltaSessionStatistics.incSessionsInvalidated();
+
+ deltaSessionStatistics.getSessionsCreated();
+ deltaSessionStatistics.getSessionsExpired();
+ deltaSessionStatistics.getSessionsInvalidated();
+
+ verify(statistics, times(3)).incLong(anyInt(), anyLong());
+ verify(statistics, times(3)).getLong(anyInt());
+ }
+}
diff --git a/extensions/geode-modules-test/src/main/java/org/apache/geode/modules/session/catalina/internal/DeltaSessionUpdateAttributeEventJUnitTest.java b/extensions/geode-modules-test/src/main/java/org/apache/geode/modules/session/catalina/internal/DeltaSessionUpdateAttributeEventJUnitTest.java
new file mode 100644
index 0000000..d356afd
--- /dev/null
+++ b/extensions/geode-modules-test/src/main/java/org/apache/geode/modules/session/catalina/internal/DeltaSessionUpdateAttributeEventJUnitTest.java
@@ -0,0 +1,38 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more contributor license
+ * agreements. See the NOTICE file distributed with this work for additional information regarding
+ * copyright ownership. The ASF licenses this file to You 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.apache.geode.modules.session.catalina.internal;
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+
+import org.junit.Test;
+
+import org.apache.geode.modules.session.catalina.DeltaSessionInterface;
+
+public class DeltaSessionUpdateAttributeEventJUnitTest {
+ @Test
+ public void DeltaSessionDestroyAttributeEventAppliesAttributeToSession() {
+ String attributeName = "UpdateAttribute";
+ String attributeValue = "UpdateValue";
+
+ DeltaSessionUpdateAttributeEvent event =
+ new DeltaSessionUpdateAttributeEvent(attributeName, attributeValue);
+ DeltaSessionInterface deltaSessionInterface = mock(DeltaSessionInterface.class);
+ event.apply((deltaSessionInterface));
+
+ verify(deltaSessionInterface).localUpdateAttribute(attributeName, attributeValue);
+ }
+}
diff --git a/extensions/geode-modules/src/test/java/org/apache/geode/modules/util/CreateRegionFunctionJUnitTest.java b/extensions/geode-modules-test/src/main/java/org/apache/geode/modules/util/CreateRegionFunctionJUnitTest.java
similarity index 100%
rename from extensions/geode-modules/src/test/java/org/apache/geode/modules/util/CreateRegionFunctionJUnitTest.java
rename to extensions/geode-modules-test/src/main/java/org/apache/geode/modules/util/CreateRegionFunctionJUnitTest.java
diff --git a/extensions/geode-modules-test/src/main/java/org/apache/geode/modules/util/TouchPartitionedRegionEntriesFunctionJUnitTest.java b/extensions/geode-modules-test/src/main/java/org/apache/geode/modules/util/TouchPartitionedRegionEntriesFunctionJUnitTest.java
new file mode 100644
index 0000000..6852681
--- /dev/null
+++ b/extensions/geode-modules-test/src/main/java/org/apache/geode/modules/util/TouchPartitionedRegionEntriesFunctionJUnitTest.java
@@ -0,0 +1,83 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more contributor license
+ * agreements. See the NOTICE file distributed with this work for additional information regarding
+ * copyright ownership. The ASF licenses this file to You 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.apache.geode.modules.util;
+
+
+import static org.assertj.core.internal.bytebuddy.matcher.ElementMatchers.any;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import java.util.HashSet;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import org.apache.geode.LogWriter;
+import org.apache.geode.cache.Cache;
+import org.apache.geode.cache.Region;
+import org.apache.geode.cache.execute.FunctionContext;
+import org.apache.geode.cache.execute.RegionFunctionContext;
+import org.apache.geode.cache.execute.ResultSender;
+
+public class TouchPartitionedRegionEntriesFunctionJUnitTest {
+
+ private TouchPartitionedRegionEntriesFunction function =
+ spy(new TouchPartitionedRegionEntriesFunction());
+ private FunctionContext context = mock(RegionFunctionContext.class);
+ private Cache cache = mock(Cache.class);
+ private LogWriter logger = mock(LogWriter.class);
+ private Region primaryDataSet = mock(Region.class);
+ private ResultSender resultSender = mock(ResultSender.class);
+
+ @Before
+ public void setUp() {
+ when(context.getCache()).thenReturn(cache);
+ when(context.getResultSender()).thenReturn(resultSender);
+ when(cache.getLogger()).thenReturn(logger);
+ when(logger.fineEnabled()).thenReturn(false);
+ doReturn(primaryDataSet).when(function)
+ .getLocalDataForContextViaRegionHelper((RegionFunctionContext) context);
+ }
+
+ @Test
+ public void executeDoesNotThrowExceptionWithProperlyDefinedContext() {
+ doReturn(new HashSet() {}).when((RegionFunctionContext) context).getFilter();
+
+ function.execute(context);
+
+ verify(primaryDataSet, times(0)).get(any());
+ verify(resultSender).lastResult(true);
+ }
+
+ @Test
+ public void executeDoesNotThrowExceptionWithProperlyDefinedContextAndMultipleKeys() {
+ HashSet<String> keys = new HashSet();
+ keys.add("Key1");
+ keys.add("Key2");
+
+ doReturn(keys).when((RegionFunctionContext) context).getFilter();
+
+ function.execute(context);
+
+ verify(primaryDataSet, times(keys.size())).get(anyString());
+ verify(resultSender).lastResult(true);
+ }
+}
diff --git a/extensions/geode-modules-test/src/main/java/org/apache/geode/modules/util/TouchReplicatedRegionEntriesFunctionJUnitTest.java b/extensions/geode-modules-test/src/main/java/org/apache/geode/modules/util/TouchReplicatedRegionEntriesFunctionJUnitTest.java
new file mode 100644
index 0000000..294317a
--- /dev/null
+++ b/extensions/geode-modules-test/src/main/java/org/apache/geode/modules/util/TouchReplicatedRegionEntriesFunctionJUnitTest.java
@@ -0,0 +1,76 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more contributor license
+ * agreements. See the NOTICE file distributed with this work for additional information regarding
+ * copyright ownership. The ASF licenses this file to You 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.apache.geode.modules.util;
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import java.util.HashSet;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import org.apache.geode.LogWriter;
+import org.apache.geode.cache.Cache;
+import org.apache.geode.cache.Region;
+import org.apache.geode.cache.execute.FunctionContext;
+import org.apache.geode.cache.execute.RegionFunctionContext;
+import org.apache.geode.cache.execute.ResultSender;
+
+public class TouchReplicatedRegionEntriesFunctionJUnitTest {
+ private TouchReplicatedRegionEntriesFunction function =
+ spy(new TouchReplicatedRegionEntriesFunction());
+ private FunctionContext context = mock(RegionFunctionContext.class);
+ private Cache cache = mock(Cache.class);
+ private LogWriter logger = mock(LogWriter.class);
+ private Region region = mock(Region.class);
+ private ResultSender resultSender = mock(ResultSender.class);
+ private String regionName = "regionName";
+ private HashSet<String> keys = new HashSet<>();
+ private Object[] arguments = new Object[] {regionName, keys};
+
+ @Before
+ public void setUp() {
+ when(context.getArguments()).thenReturn(arguments);
+ when(context.getCache()).thenReturn(cache);
+ when(context.getResultSender()).thenReturn(resultSender);
+ when(cache.getLogger()).thenReturn(logger);
+ when(logger.fineEnabled()).thenReturn(false);
+ }
+
+ @Test
+ public void executeDoesNotThrowExceptionWithProperlyDefinedContext() {
+ when(cache.getRegion(regionName)).thenReturn(region);
+
+ function.execute(context);
+
+ verify(region).getAll(keys);
+ verify(resultSender).lastResult(true);
+ }
+
+ @Test
+ public void executeDoesNotThrowExceptionWithProperlyDefinedContextAndNullRegion() {
+ when(cache.getRegion(regionName)).thenReturn(null);
+
+ function.execute(context);
+
+ verify(region, times(0)).getAll(keys);
+ verify(resultSender).lastResult(true);
+ }
+}
diff --git a/extensions/geode-modules-tomcat7/build.gradle b/extensions/geode-modules-tomcat7/build.gradle
index f5ff7e9..4c390ba 100644
--- a/extensions/geode-modules-tomcat7/build.gradle
+++ b/extensions/geode-modules-tomcat7/build.gradle
@@ -34,6 +34,10 @@
// Remove everything related to Tomcat 6.x
exclude group: 'org.apache.tomcat'
}
+ testCompile(project(':extensions:geode-modules')) {
+ // Remove everything related to Tomcat 6.x
+ exclude group: 'org.apache.tomcat'
+ }
compile('org.apache.tomcat:tomcat-catalina:' + DependencyConstraints.get('tomcat7.version')) {
exclude module: 'tomcat-annotations-api'
@@ -44,6 +48,12 @@
}
compile('org.apache.tomcat:tomcat-juli:' + DependencyConstraints.get('tomcat7.version'))
+
+ testCompile('org.httpunit:httpunit')
+ testCompile('junit:junit')
+ testCompile('org.assertj:assertj-core')
+ testCompile('org.mockito:mockito-core')
+ testCompile(project(':extensions:geode-modules-test'))
integrationTestCompile(project(':geode-dunit')) {
exclude module: 'geode-core'
}
diff --git a/extensions/geode-modules-tomcat7/src/main/java/org/apache/geode/modules/session/catalina/Tomcat7DeltaSessionManager.java b/extensions/geode-modules-tomcat7/src/main/java/org/apache/geode/modules/session/catalina/Tomcat7DeltaSessionManager.java
index 7bbe80f..e965cc5 100644
--- a/extensions/geode-modules-tomcat7/src/main/java/org/apache/geode/modules/session/catalina/Tomcat7DeltaSessionManager.java
+++ b/extensions/geode-modules-tomcat7/src/main/java/org/apache/geode/modules/session/catalina/Tomcat7DeltaSessionManager.java
@@ -39,7 +39,7 @@
*/
@Override
public void startInternal() throws LifecycleException {
- super.startInternal();
+ startInternalBase();
if (getLogger().isDebugEnabled()) {
getLogger().debug(this + ": Starting");
}
@@ -69,7 +69,15 @@
scheduleTimerTasks();
this.started.set(true);
- this.setState(LifecycleState.STARTING);
+ this.setLifecycleState(LifecycleState.STARTING);
+ }
+
+ void setLifecycleState(LifecycleState newState) throws LifecycleException {
+ this.setState(newState);
+ }
+
+ void startInternalBase() throws LifecycleException {
+ super.startInternal();
}
/**
@@ -80,7 +88,7 @@
*/
@Override
public void stopInternal() throws LifecycleException {
- super.stopInternal();
+ stopInternalBase();
if (getLogger().isDebugEnabled()) {
getLogger().debug(this + ": Stopping");
}
@@ -112,7 +120,15 @@
unregisterCommitSessionValve();
}
- this.setState(LifecycleState.STOPPING);
+ setLifecycleState(LifecycleState.STOPPING);
+ }
+
+ void stopInternalBase() throws LifecycleException {
+ super.stopInternal();
+ }
+
+ void destroyInternalBase() throws LifecycleException {
+ super.destroyInternal();
}
/**
diff --git a/extensions/geode-modules-tomcat7/src/test/java/org/apache/geode/modules/session/catalina/Tomcat7DeltaSessionManagerJUnitTest.java b/extensions/geode-modules-tomcat7/src/test/java/org/apache/geode/modules/session/catalina/Tomcat7DeltaSessionManagerJUnitTest.java
new file mode 100644
index 0000000..f1bee51
--- /dev/null
+++ b/extensions/geode-modules-tomcat7/src/test/java/org/apache/geode/modules/session/catalina/Tomcat7DeltaSessionManagerJUnitTest.java
@@ -0,0 +1,129 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more contributor license
+ * agreements. See the NOTICE file distributed with this work for additional information regarding
+ * copyright ownership. The ASF licenses this file to You 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.apache.geode.modules.session.catalina;
+
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+
+import java.io.IOException;
+
+import org.apache.catalina.Context;
+import org.apache.catalina.LifecycleException;
+import org.apache.catalina.LifecycleState;
+import org.apache.catalina.Pipeline;
+import org.junit.Before;
+import org.junit.Test;
+
+import org.apache.geode.internal.cache.GemFireCacheImpl;
+
+public class Tomcat7DeltaSessionManagerJUnitTest extends DeltaSessionManagerJUnitTest {
+ private Pipeline pipeline;
+
+ @Before
+ public void setup() {
+ manager = spy(new Tomcat7DeltaSessionManager());
+ initTest();
+ pipeline = mock(Pipeline.class);
+ }
+
+ @Test
+ public void startInternalSucceedsInitialRun()
+ throws LifecycleException, IOException, ClassNotFoundException {
+ doNothing().when((Tomcat7DeltaSessionManager) manager).startInternalBase();
+ doReturn(true).when(manager).isCommitValveEnabled();
+ doReturn(cache).when(manager).getAnyCacheInstance();
+ doReturn(true).when((GemFireCacheImpl) cache).isClient();
+ doNothing().when(manager).initSessionCache();
+ doReturn(pipeline).when(manager).getPipeline();
+
+ // Unit testing for load is handled in the parent DeltaSessionManagerJUnitTest class
+ doNothing().when(manager).load();
+
+ doNothing().when((Tomcat7DeltaSessionManager) manager)
+ .setLifecycleState(LifecycleState.STARTING);
+
+ assertThat(manager.started).isFalse();
+ ((Tomcat7DeltaSessionManager) manager).startInternal();
+ assertThat(manager.started).isTrue();
+ verify((Tomcat7DeltaSessionManager) manager).setLifecycleState(LifecycleState.STARTING);
+ }
+
+ @Test
+ public void startInternalDoesNotReinitializeManagerOnSubsequentCalls()
+ throws LifecycleException, IOException, ClassNotFoundException {
+ doNothing().when((Tomcat7DeltaSessionManager) manager).startInternalBase();
+ doReturn(true).when(manager).isCommitValveEnabled();
+ doReturn(cache).when(manager).getAnyCacheInstance();
+ doReturn(true).when((GemFireCacheImpl) cache).isClient();
+ doNothing().when(manager).initSessionCache();
+ doReturn(pipeline).when(manager).getPipeline();
+
+ // Unit testing for load is handled in the parent DeltaSessionManagerJUnitTest class
+ doNothing().when(manager).load();
+
+ doNothing().when((Tomcat7DeltaSessionManager) manager)
+ .setLifecycleState(LifecycleState.STARTING);
+
+ assertThat(manager.started).isFalse();
+ ((Tomcat7DeltaSessionManager) manager).startInternal();
+
+ // Verify that various initialization actions were performed
+ assertThat(manager.started).isTrue();
+ verify(manager).initializeSessionCache();
+ verify((Tomcat7DeltaSessionManager) manager).setLifecycleState(LifecycleState.STARTING);
+
+ // Rerun startInternal
+ ((Tomcat7DeltaSessionManager) manager).startInternal();
+
+ // Verify that the initialization actions were still only performed one time
+ verify(manager).initializeSessionCache();
+ verify((Tomcat7DeltaSessionManager) manager).setLifecycleState(LifecycleState.STARTING);
+ }
+
+ @Test
+ public void stopInternal() throws LifecycleException, IOException {
+ doNothing().when((Tomcat7DeltaSessionManager) manager).startInternalBase();
+ doNothing().when((Tomcat7DeltaSessionManager) manager).destroyInternalBase();
+ doReturn(true).when(manager).isCommitValveEnabled();
+
+ // Unit testing for unload is handled in the parent DeltaSessionManagerJUnitTest class
+ doNothing().when(manager).unload();
+
+ doNothing().when((Tomcat7DeltaSessionManager) manager)
+ .setLifecycleState(LifecycleState.STOPPING);
+
+ ((Tomcat7DeltaSessionManager) manager).stopInternal();
+
+ assertThat(manager.started).isFalse();
+ verify((Tomcat7DeltaSessionManager) manager).setLifecycleState(LifecycleState.STOPPING);
+ }
+
+ @Test
+ public void setContainerSetsProperContainerAndMaxInactiveInterval() {
+ Context container = mock(Context.class);
+ int containerMaxInactiveInterval = 3;
+
+ doReturn(containerMaxInactiveInterval).when(container).getSessionTimeout();
+
+ manager.setContainer(container);
+ verify(manager).setMaxInactiveInterval(containerMaxInactiveInterval * 60);
+ }
+}
diff --git a/extensions/geode-modules-tomcat8/build.gradle b/extensions/geode-modules-tomcat8/build.gradle
index f8c7730..721d08d 100644
--- a/extensions/geode-modules-tomcat8/build.gradle
+++ b/extensions/geode-modules-tomcat8/build.gradle
@@ -28,12 +28,23 @@
distributedTestCompile('junit:junit')
compile('mx4j:mx4j')
distributedTestImplementation(project(':geode-logging'))
+ testCompile('org.httpunit:httpunit')
+ testCompile('org.apache.tomcat:tomcat-jaspic-api:' + DependencyConstraints.get('tomcat8.version'))
+ testCompile('org.httpunit:httpunit')
+ testCompile('junit:junit')
+ testCompile('org.assertj:assertj-core')
+ testCompile('org.mockito:mockito-core')
+ testCompile(project(':extensions:geode-modules-test'))
distributedTestCompile('org.httpunit:httpunit')
distributedTestCompile('org.apache.tomcat:tomcat-jaspic-api:' + DependencyConstraints.get('tomcat8.version'))
compile(project(':geode-core'))
compile(project(':extensions:geode-modules')) {
exclude group: 'org.apache.tomcat'
}
+ testCompile(project(':extensions:geode-modules')) {
+ exclude group: 'org.apache.tomcat'
+ }
+
compile('org.apache.tomcat:tomcat-catalina:' + DependencyConstraints.get('tomcat8.version')) {
exclude module: 'tomcat-annotations-api'
@@ -44,6 +55,16 @@
}
compile('org.apache.tomcat:tomcat-juli:' + DependencyConstraints.get('tomcat8.version'))
compile('javax.servlet:javax.servlet-api')
+
+ integrationTestCompile(project(':geode-dunit')) {
+ exclude module: 'geode-core'
+ }
+ integrationTestCompile(project(':geode-junit')) {
+ exclude module: 'geode-core'
+ }
+ integrationTestCompile(project(':extensions:geode-modules-test'))
+ integrationTestRuntime('xerces:xercesImpl')
+ integrationTestRuntime('javax.annotation:javax.annotation-api')
distributedTestCompile(project(':geode-dunit')) {
exclude module: 'geode-core'
diff --git a/extensions/geode-modules-tomcat8/src/main/java/org/apache/geode/modules/session/catalina/Tomcat8DeltaSessionManager.java b/extensions/geode-modules-tomcat8/src/main/java/org/apache/geode/modules/session/catalina/Tomcat8DeltaSessionManager.java
index 8752b61..8a32ac0 100644
--- a/extensions/geode-modules-tomcat8/src/main/java/org/apache/geode/modules/session/catalina/Tomcat8DeltaSessionManager.java
+++ b/extensions/geode-modules-tomcat8/src/main/java/org/apache/geode/modules/session/catalina/Tomcat8DeltaSessionManager.java
@@ -34,7 +34,7 @@
*/
@Override
public void startInternal() throws LifecycleException {
- super.startInternal();
+ startInternalBase();
if (getLogger().isDebugEnabled()) {
getLogger().debug(this + ": Starting");
}
@@ -64,7 +64,15 @@
scheduleTimerTasks();
this.started.set(true);
- this.setState(LifecycleState.STARTING);
+ setLifecycleState(LifecycleState.STARTING);
+ }
+
+ void setLifecycleState(LifecycleState newState) throws LifecycleException {
+ this.setState(newState);
+ }
+
+ void startInternalBase() throws LifecycleException {
+ super.startInternal();
}
/**
@@ -75,7 +83,7 @@
*/
@Override
public void stopInternal() throws LifecycleException {
- super.stopInternal();
+ stopInternalBase();
if (getLogger().isDebugEnabled()) {
getLogger().debug(this + ": Stopping");
}
@@ -92,7 +100,7 @@
// StandardManager expires all Sessions here.
// All Sessions are not known by this Manager.
- super.destroyInternal();
+ destroyInternalBase();
// Clear any sessions to be touched
getSessionsToTouch().clear();
@@ -107,10 +115,18 @@
unregisterCommitSessionValve();
}
- this.setState(LifecycleState.STOPPING);
+ setLifecycleState(LifecycleState.STOPPING);
}
+ void stopInternalBase() throws LifecycleException {
+ super.stopInternal();
+ }
+
+ void destroyInternalBase() throws LifecycleException {
+ super.destroyInternal();
+ }
+
@Override
public int getMaxInactiveInterval() {
return getContext().getSessionTimeout();
diff --git a/extensions/geode-modules-tomcat8/src/test/java/org/apache/geode/modules/session/catalina/Tomcat8DeltaSessionManagerJUnitTest.java b/extensions/geode-modules-tomcat8/src/test/java/org/apache/geode/modules/session/catalina/Tomcat8DeltaSessionManagerJUnitTest.java
new file mode 100644
index 0000000..1bf7939
--- /dev/null
+++ b/extensions/geode-modules-tomcat8/src/test/java/org/apache/geode/modules/session/catalina/Tomcat8DeltaSessionManagerJUnitTest.java
@@ -0,0 +1,119 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more contributor license
+ * agreements. See the NOTICE file distributed with this work for additional information regarding
+ * copyright ownership. The ASF licenses this file to You 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.apache.geode.modules.session.catalina;
+
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+
+import java.io.IOException;
+
+import org.apache.catalina.LifecycleException;
+import org.apache.catalina.LifecycleState;
+import org.apache.catalina.Pipeline;
+import org.junit.Before;
+import org.junit.Test;
+
+import org.apache.geode.internal.cache.GemFireCacheImpl;
+
+public class Tomcat8DeltaSessionManagerJUnitTest extends DeltaSessionManagerJUnitTest {
+ private Pipeline pipeline;
+
+ @Before
+ public void setup() {
+ manager = spy(new Tomcat8DeltaSessionManager());
+ initTest();
+ pipeline = mock(Pipeline.class);
+ doReturn(context).when(manager).getContext();
+ }
+
+ @Test
+ public void startInternalSucceedsInitialRun()
+ throws LifecycleException, IOException, ClassNotFoundException {
+ doNothing().when((Tomcat8DeltaSessionManager) manager).startInternalBase();
+ doReturn(true).when(manager).isCommitValveEnabled();
+ doReturn(cache).when(manager).getAnyCacheInstance();
+ doReturn(true).when((GemFireCacheImpl) cache).isClient();
+ doNothing().when(manager).initSessionCache();
+ doReturn(pipeline).when(manager).getPipeline();
+
+ // Unit testing for load is handled in the parent DeltaSessionManagerJUnitTest class
+ doNothing().when(manager).load();
+
+ doNothing().when((Tomcat8DeltaSessionManager) manager)
+ .setLifecycleState(LifecycleState.STARTING);
+
+ assertThat(manager.started).isFalse();
+ ((Tomcat8DeltaSessionManager) manager).startInternal();
+ assertThat(manager.started).isTrue();
+ verify((Tomcat8DeltaSessionManager) manager).setLifecycleState(LifecycleState.STARTING);
+ }
+
+ @Test
+ public void startInternalDoesNotReinitializeManagerOnSubsequentCalls()
+ throws LifecycleException, IOException, ClassNotFoundException {
+ doNothing().when((Tomcat8DeltaSessionManager) manager).startInternalBase();
+ doReturn(true).when(manager).isCommitValveEnabled();
+ doReturn(cache).when(manager).getAnyCacheInstance();
+ doReturn(true).when((GemFireCacheImpl) cache).isClient();
+ doNothing().when(manager).initSessionCache();
+ doReturn(pipeline).when(manager).getPipeline();
+
+ // Unit testing for load is handled in the parent DeltaSessionManagerJUnitTest class
+ doNothing().when(manager).load();
+
+ doNothing().when((Tomcat8DeltaSessionManager) manager)
+ .setLifecycleState(LifecycleState.STARTING);
+
+ assertThat(manager.started).isFalse();
+ ((Tomcat8DeltaSessionManager) manager).startInternal();
+
+ // Verify that various initialization actions were performed
+ assertThat(manager.started).isTrue();
+ verify(manager).initializeSessionCache();
+ verify((Tomcat8DeltaSessionManager) manager).setLifecycleState(LifecycleState.STARTING);
+
+ // Rerun startInternal
+ ((Tomcat8DeltaSessionManager) manager).startInternal();
+
+ // Verify that the initialization actions were still only performed one time
+ verify(manager).initializeSessionCache();
+ verify((Tomcat8DeltaSessionManager) manager).setLifecycleState(LifecycleState.STARTING);
+ }
+
+ @Test
+ public void stopInternal() throws LifecycleException, IOException {
+ doNothing().when((Tomcat8DeltaSessionManager) manager).startInternalBase();
+ doNothing().when((Tomcat8DeltaSessionManager) manager).destroyInternalBase();
+ doReturn(true).when(manager).isCommitValveEnabled();
+
+ // Unit testing for unload is handled in the parent DeltaSessionManagerJUnitTest class
+ doNothing().when(manager).unload();
+
+ doNothing().when((Tomcat8DeltaSessionManager) manager)
+ .setLifecycleState(LifecycleState.STOPPING);
+
+ ((Tomcat8DeltaSessionManager) manager).stopInternal();
+
+ assertThat(manager.started).isFalse();
+ verify((Tomcat8DeltaSessionManager) manager).setLifecycleState(LifecycleState.STOPPING);
+ }
+
+}
diff --git a/extensions/geode-modules-tomcat9/build.gradle b/extensions/geode-modules-tomcat9/build.gradle
index 280e530..417714a 100644
--- a/extensions/geode-modules-tomcat9/build.gradle
+++ b/extensions/geode-modules-tomcat9/build.gradle
@@ -28,6 +28,9 @@
compile(project(':extensions:geode-modules')) {
exclude group: 'org.apache.tomcat'
}
+ testCompile(project(':extensions:geode-modules')) {
+ exclude group: 'org.apache.tomcat'
+ }
compile('org.apache.tomcat:tomcat-catalina:' + DependencyConstraints.get('tomcat9.version')) {
exclude module: 'tomcat-annotations-api'
@@ -39,6 +42,12 @@
compile('org.apache.tomcat:tomcat-juli:' + DependencyConstraints.get('tomcat9.version'))
compile('javax.servlet:javax.servlet-api:' + '3.1.0')
+ testCompile('org.httpunit:httpunit')
+ testCompile('junit:junit')
+ testCompile('org.assertj:assertj-core')
+ testCompile('org.mockito:mockito-core')
+ testCompile(project(':extensions:geode-modules-test'))
+
distributedTestCompile(project(':extensions:geode-modules-test'))
distributedTestRuntime('xerces:xercesImpl')
diff --git a/extensions/geode-modules-tomcat9/src/main/java/org/apache/geode/modules/session/catalina/Tomcat9DeltaSessionManager.java b/extensions/geode-modules-tomcat9/src/main/java/org/apache/geode/modules/session/catalina/Tomcat9DeltaSessionManager.java
index 973bb3e..ac9ac2c 100644
--- a/extensions/geode-modules-tomcat9/src/main/java/org/apache/geode/modules/session/catalina/Tomcat9DeltaSessionManager.java
+++ b/extensions/geode-modules-tomcat9/src/main/java/org/apache/geode/modules/session/catalina/Tomcat9DeltaSessionManager.java
@@ -34,7 +34,7 @@
*/
@Override
public void startInternal() throws LifecycleException {
- super.startInternal();
+ startInternalBase();
if (getLogger().isDebugEnabled()) {
getLogger().debug(this + ": Starting");
}
@@ -64,7 +64,15 @@
scheduleTimerTasks();
this.started.set(true);
- this.setState(LifecycleState.STARTING);
+ setLifecycleState(LifecycleState.STARTING);
+ }
+
+ void setLifecycleState(LifecycleState newState) throws LifecycleException {
+ this.setState(newState);
+ }
+
+ void startInternalBase() throws LifecycleException {
+ super.startInternal();
}
/**
@@ -75,7 +83,7 @@
*/
@Override
public void stopInternal() throws LifecycleException {
- super.stopInternal();
+ stopInternalBase();
if (getLogger().isDebugEnabled()) {
getLogger().debug(this + ": Stopping");
}
@@ -92,7 +100,7 @@
// StandardManager expires all Sessions here.
// All Sessions are not known by this Manager.
- super.destroyInternal();
+ destroyInternalBase();
// Clear any sessions to be touched
getSessionsToTouch().clear();
@@ -107,10 +115,18 @@
unregisterCommitSessionValve();
}
- this.setState(LifecycleState.STOPPING);
+ setLifecycleState(LifecycleState.STOPPING);
}
+ void stopInternalBase() throws LifecycleException {
+ super.stopInternal();
+ }
+
+ void destroyInternalBase() throws LifecycleException {
+ super.destroyInternal();
+ }
+
@Override
public int getMaxInactiveInterval() {
return getContext().getSessionTimeout();
diff --git a/extensions/geode-modules-tomcat9/src/test/java/org/apache/geode/modules/session/catalina/Tomcat9DeltaSessionManagerJUnitTest.java b/extensions/geode-modules-tomcat9/src/test/java/org/apache/geode/modules/session/catalina/Tomcat9DeltaSessionManagerJUnitTest.java
new file mode 100644
index 0000000..cc55763
--- /dev/null
+++ b/extensions/geode-modules-tomcat9/src/test/java/org/apache/geode/modules/session/catalina/Tomcat9DeltaSessionManagerJUnitTest.java
@@ -0,0 +1,119 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more contributor license
+ * agreements. See the NOTICE file distributed with this work for additional information regarding
+ * copyright ownership. The ASF licenses this file to You 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.apache.geode.modules.session.catalina;
+
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+
+import java.io.IOException;
+
+import org.apache.catalina.LifecycleException;
+import org.apache.catalina.LifecycleState;
+import org.apache.catalina.Pipeline;
+import org.junit.Before;
+import org.junit.Test;
+
+import org.apache.geode.internal.cache.GemFireCacheImpl;
+
+public class Tomcat9DeltaSessionManagerJUnitTest extends DeltaSessionManagerJUnitTest {
+ private Pipeline pipeline;
+
+ @Before
+ public void setup() {
+ manager = spy(new Tomcat9DeltaSessionManager());
+ initTest();
+ pipeline = mock(Pipeline.class);
+ doReturn(context).when(manager).getContext();
+ }
+
+ @Test
+ public void startInternalSucceedsInitialRun()
+ throws LifecycleException, IOException, ClassNotFoundException {
+ doNothing().when((Tomcat9DeltaSessionManager) manager).startInternalBase();
+ doReturn(true).when(manager).isCommitValveEnabled();
+ doReturn(cache).when(manager).getAnyCacheInstance();
+ doReturn(true).when((GemFireCacheImpl) cache).isClient();
+ doNothing().when(manager).initSessionCache();
+ doReturn(pipeline).when(manager).getPipeline();
+
+ // Unit testing for load is handled in the parent DeltaSessionManagerJUnitTest class
+ doNothing().when(manager).load();
+
+ doNothing().when((Tomcat9DeltaSessionManager) manager)
+ .setLifecycleState(LifecycleState.STARTING);
+
+ assertThat(manager.started).isFalse();
+ ((Tomcat9DeltaSessionManager) manager).startInternal();
+ assertThat(manager.started).isTrue();
+ verify((Tomcat9DeltaSessionManager) manager).setLifecycleState(LifecycleState.STARTING);
+ }
+
+ @Test
+ public void startInternalDoesNotReinitializeManagerOnSubsequentCalls()
+ throws LifecycleException, IOException, ClassNotFoundException {
+ doNothing().when((Tomcat9DeltaSessionManager) manager).startInternalBase();
+ doReturn(true).when(manager).isCommitValveEnabled();
+ doReturn(cache).when(manager).getAnyCacheInstance();
+ doReturn(true).when((GemFireCacheImpl) cache).isClient();
+ doNothing().when(manager).initSessionCache();
+ doReturn(pipeline).when(manager).getPipeline();
+
+ // Unit testing for load is handled in the parent DeltaSessionManagerJUnitTest class
+ doNothing().when(manager).load();
+
+ doNothing().when((Tomcat9DeltaSessionManager) manager)
+ .setLifecycleState(LifecycleState.STARTING);
+
+ assertThat(manager.started).isFalse();
+ ((Tomcat9DeltaSessionManager) manager).startInternal();
+
+ // Verify that various initialization actions were performed
+ assertThat(manager.started).isTrue();
+ verify(manager).initializeSessionCache();
+ verify((Tomcat9DeltaSessionManager) manager).setLifecycleState(LifecycleState.STARTING);
+
+ // Rerun startInternal
+ ((Tomcat9DeltaSessionManager) manager).startInternal();
+
+ // Verify that the initialization actions were still only performed one time
+ verify(manager).initializeSessionCache();
+ verify((Tomcat9DeltaSessionManager) manager).setLifecycleState(LifecycleState.STARTING);
+ }
+
+ @Test
+ public void stopInternal() throws LifecycleException, IOException {
+ doNothing().when((Tomcat9DeltaSessionManager) manager).startInternalBase();
+ doNothing().when((Tomcat9DeltaSessionManager) manager).destroyInternalBase();
+ doReturn(true).when(manager).isCommitValveEnabled();
+
+ // Unit testing for unload is handled in the parent DeltaSessionManagerJUnitTest class
+ doNothing().when(manager).unload();
+
+ doNothing().when((Tomcat9DeltaSessionManager) manager)
+ .setLifecycleState(LifecycleState.STOPPING);
+
+ ((Tomcat9DeltaSessionManager) manager).stopInternal();
+
+ assertThat(manager.started).isFalse();
+ verify((Tomcat9DeltaSessionManager) manager).setLifecycleState(LifecycleState.STOPPING);
+ }
+
+}
diff --git a/extensions/geode-modules/src/main/java/org/apache/geode/modules/session/catalina/AbstractSessionCache.java b/extensions/geode-modules/src/main/java/org/apache/geode/modules/session/catalina/AbstractSessionCache.java
index 254bf57..f4aada3 100644
--- a/extensions/geode-modules/src/main/java/org/apache/geode/modules/session/catalina/AbstractSessionCache.java
+++ b/extensions/geode-modules/src/main/java/org/apache/geode/modules/session/catalina/AbstractSessionCache.java
@@ -96,7 +96,7 @@
}
RegionConfiguration createRegionConfiguration() {
- RegionConfiguration configuration = new RegionConfiguration();
+ RegionConfiguration configuration = getNewRegionConfiguration();
configuration.setRegionName(getSessionManager().getRegionName());
configuration.setRegionAttributesId(getSessionManager().getRegionAttributesId());
if (getSessionManager()
@@ -110,4 +110,9 @@
configuration.setEnableDebugListener(getSessionManager().getEnableDebugListener());
return configuration;
}
+
+ // Helper methods added to improve unit testing of class
+ RegionConfiguration getNewRegionConfiguration() {
+ return new RegionConfiguration();
+ }
}
diff --git a/extensions/geode-modules/src/main/java/org/apache/geode/modules/session/catalina/ClientServerSessionCache.java b/extensions/geode-modules/src/main/java/org/apache/geode/modules/session/catalina/ClientServerSessionCache.java
index 0803a4c..952e4cd 100644
--- a/extensions/geode-modules/src/main/java/org/apache/geode/modules/session/catalina/ClientServerSessionCache.java
+++ b/extensions/geode-modules/src/main/java/org/apache/geode/modules/session/catalina/ClientServerSessionCache.java
@@ -98,7 +98,7 @@
// Invoke the appropriate function depending on the type of region
if (regionAttributesID.startsWith("partition")) {
// Execute the partitioned touch function on the primary server(s)
- Execution execution = FunctionService.onRegion(getSessionRegion()).withFilter(sessionIds);
+ Execution execution = getExecutionForFunctionOnRegionWithFilter(sessionIds);
try {
ResultCollector collector = execution.execute(TouchPartitionedRegionEntriesFunction.ID);
collector.getResult();
@@ -108,8 +108,8 @@
}
} else {
// Execute the member touch function on all the server(s)
- Execution execution = FunctionService.onServers(getCache())
- .setArguments(new Object[] {this.sessionRegion.getFullPath(), sessionIds});
+ Object[] arguments = new Object[] {this.sessionRegion.getFullPath(), sessionIds};
+ Execution execution = getExecutionForFunctionOnServersWithArguments(arguments);
try {
ResultCollector collector = execution.execute(TouchReplicatedRegionEntriesFunction.ID);
collector.getResult();
@@ -143,7 +143,7 @@
@Override
public boolean isBackingCacheAvailable() {
if (getSessionManager().isCommitValveFailfastEnabled()) {
- PoolImpl pool = (PoolImpl) PoolManager.find(getOperatingRegionName());
+ PoolImpl pool = findPoolInPoolManager();
return pool.isPrimaryUpdaterAlive();
}
return true;
@@ -155,7 +155,7 @@
}
private void bootstrapServers() {
- Execution execution = FunctionService.onServers(this.cache);
+ Execution execution = getExecutionForFunctionOnServers();
ResultCollector collector = execution.execute(new BootstrappingFunction());
// Get the result. Nothing is being done with it.
try {
@@ -202,12 +202,12 @@
.anyMatch(x -> x instanceof SessionExpirationCacheListener);
}
- private void createSessionRegionOnServers() {
+ void createSessionRegionOnServers() {
// Create the RegionConfiguration
RegionConfiguration configuration = createRegionConfiguration();
// Send it to the server tier
- Execution execution = FunctionService.onServer(this.cache).setArguments(configuration);
+ Execution execution = getExecutionForFunctionOnServerWithRegionConfiguration(configuration);
ResultCollector collector = execution.execute(CreateRegionFunction.ID);
// Verify the region was successfully created on the servers
@@ -225,7 +225,7 @@
}
}
- private Region<String, HttpSession> createLocalSessionRegion() {
+ Region<String, HttpSession> createLocalSessionRegion() {
ClientRegionFactory<String, HttpSession> factory = null;
if (getSessionManager().getEnableLocalCache()) {
// Create the region factory with caching and heap LRU enabled
@@ -257,4 +257,37 @@
return region;
}
+
+ // Helper methods added to improve unit testing of class
+ Execution getExecutionForFunctionOnServers() {
+ return getExecutionForFunctionOnServersWithArguments(null);
+ }
+
+ Execution getExecutionForFunctionOnServersWithArguments(Object[] arguments) {
+ if (arguments != null && arguments.length > 0) {
+ return FunctionService.onServers(getCache()).setArguments(arguments);
+ } else {
+ return FunctionService.onServers(getCache());
+ }
+ }
+
+ Execution getExecutionForFunctionOnServerWithRegionConfiguration(RegionConfiguration arguments) {
+ if (arguments != null) {
+ return FunctionService.onServer(getCache()).setArguments(arguments);
+ } else {
+ return FunctionService.onServer(getCache());
+ }
+ }
+
+ Execution getExecutionForFunctionOnRegionWithFilter(Set<?> filter) {
+ if (filter != null && filter.size() > 0) {
+ return FunctionService.onRegion(getSessionRegion()).withFilter(filter);
+ } else {
+ return FunctionService.onRegion(getSessionRegion());
+ }
+ }
+
+ PoolImpl findPoolInPoolManager() {
+ return (PoolImpl) PoolManager.find(getOperatingRegionName());
+ }
}
diff --git a/extensions/geode-modules/src/main/java/org/apache/geode/modules/session/catalina/DeltaSession.java b/extensions/geode-modules/src/main/java/org/apache/geode/modules/session/catalina/DeltaSession.java
index 0be6d03..aa8b3f5 100644
--- a/extensions/geode-modules/src/main/java/org/apache/geode/modules/session/catalina/DeltaSession.java
+++ b/extensions/geode-modules/src/main/java/org/apache/geode/modules/session/catalina/DeltaSession.java
@@ -115,10 +115,9 @@
@SuppressWarnings("unchecked")
public HttpSession getSession() {
if (facade == null) {
- if (SecurityUtil.isPackageProtectionEnabled()) {
+ if (isPackageProtectionEnabled()) {
final DeltaSession fsession = this;
- facade = (DeltaSessionFacade) AccessController.doPrivileged(
- (PrivilegedAction) () -> new DeltaSessionFacade(fsession));
+ facade = getNewFacade(fsession);
} else {
facade = new DeltaSessionFacade(this);
}
@@ -191,7 +190,7 @@
return this.operatingRegion;
}
- private boolean isCommitEnabled() {
+ boolean isCommitEnabled() {
DeltaSessionManager mgr = (DeltaSessionManager) getManager();
return mgr.isCommitValveEnabled();
}
@@ -240,7 +239,9 @@
@Override
public void setAttribute(String name, Object value, boolean notify) {
+
checkBackingCacheAvailable();
+
synchronized (this.changeLock) {
// Serialize the value
byte[] serializedValue = serialize(value);
@@ -261,6 +262,7 @@
new DeltaSessionUpdateAttributeEvent(name, serializedValue);
queueAttributeEvent(event, true);
+
// Distribute the update
if (!isCommitEnabled()) {
putInRegion(getOperatingRegion(), true, null);
@@ -318,6 +320,10 @@
return value;
}
+ Object getAttributeWithoutDeserialize(String name) {
+ return super.getAttribute(name);
+ }
+
@Override
public void invalidate() {
super.invalidate();
@@ -414,7 +420,7 @@
}
}
}
- this.eventQueue.add(event);
+ addEventToEventQueue(event);
}
@SuppressWarnings("unchecked")
@@ -600,8 +606,8 @@
@SuppressWarnings("unchecked")
Enumeration<String> attributeNames = (Enumeration<String>) getAttributeNames();
while (attributeNames.hasMoreElements()) {
- // Don't use this.getAttribute() because we don't want to deserialize the value.
- Object value = super.getAttribute(attributeNames.nextElement());
+ // Don't use getAttribute() because we don't want to deserialize the value.
+ Object value = getAttributeWithoutDeserialize(attributeNames.nextElement());
if (value instanceof byte[]) {
size += ((byte[]) value).length;
}
@@ -634,10 +640,10 @@
throw new IllegalStateException("Unable to access attributes field");
}
- private byte[] serialize(Object obj) {
+ byte[] serialize(Object obj) {
byte[] serializedValue = null;
try {
- serializedValue = BlobHelper.serializeToBlob(obj);
+ serializedValue = serializeViaBlobHelper(obj);
} catch (IOException e) {
String builder = this + ": Object " + obj
+ " cannot be serialized due to the following exception";
@@ -647,6 +653,11 @@
return serializedValue;
}
+ byte[] serializeViaBlobHelper(Object obj) throws IOException {
+ return BlobHelper.serializeToBlob(obj);
+ }
+
+
@Override
public String toString() {
return "DeltaSession[" + "id=" + getId()
@@ -655,4 +666,18 @@
+ (getOperatingRegion() == null ? "unset" : getOperatingRegion().getFullPath())
+ "]";
}
+
+ // Helper methods to enable better unit testing
+ DeltaSessionFacade getNewFacade(DeltaSessionInterface fSession) {
+ return (DeltaSessionFacade) AccessController.doPrivileged(
+ (PrivilegedAction) () -> new DeltaSessionFacade(fSession));
+ }
+
+ boolean isPackageProtectionEnabled() {
+ return SecurityUtil.isPackageProtectionEnabled();
+ }
+
+ void addEventToEventQueue(DeltaSessionAttributeEvent event) {
+ eventQueue.add(event);
+ }
}
diff --git a/extensions/geode-modules/src/main/java/org/apache/geode/modules/session/catalina/DeltaSessionManager.java b/extensions/geode-modules/src/main/java/org/apache/geode/modules/session/catalina/DeltaSessionManager.java
index be1142d..09dacde 100644
--- a/extensions/geode-modules/src/main/java/org/apache/geode/modules/session/catalina/DeltaSessionManager.java
+++ b/extensions/geode-modules/src/main/java/org/apache/geode/modules/session/catalina/DeltaSessionManager.java
@@ -29,6 +29,7 @@
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
+import java.util.List;
import java.util.Set;
import java.util.Timer;
import java.util.TimerTask;
@@ -49,6 +50,7 @@
import org.apache.juli.logging.Log;
import org.apache.juli.logging.LogFactory;
+import org.apache.geode.cache.Cache;
import org.apache.geode.cache.CacheFactory;
import org.apache.geode.cache.Region;
import org.apache.geode.cache.query.Query;
@@ -63,6 +65,9 @@
public abstract class DeltaSessionManager extends ManagerBase
implements Lifecycle, PropertyChangeListener, SessionManager {
+ static final String catalinaBaseSystemProperty = "catalina.base";
+ static final String javaTempDirSystemProperty = "java.io.tmpdir";
+ static final String fileSeparatorSystemProperty = "file.separator";
/**
* The number of rejected sessions.
*/
@@ -372,7 +377,7 @@
protected void initializeSessionCache() {
// Retrieve the cache
- GemFireCacheImpl cache = (GemFireCacheImpl) CacheFactory.getAnyInstance();
+ GemFireCacheImpl cache = (GemFireCacheImpl) getAnyCacheInstance();
if (cache == null) {
throw new IllegalStateException(
"No cache exists. Please configure either a PeerToPeerCacheLifecycleListener or ClientServerCacheLifecycleListener in the server.xml file.");
@@ -383,9 +388,17 @@
: new PeerToPeerSessionCache(this, cache);
// Initialize the session cache
+ initSessionCache();
+ }
+
+ void initSessionCache() {
this.sessionCache.initialize();
}
+ Cache getAnyCacheInstance() {
+ return CacheFactory.getAnyInstance();
+ }
+
@Override
protected StandardSession getNewSession() {
return new DeltaSession(this);
@@ -570,7 +583,7 @@
getPipeline().addValve(jvmRouteBinderValve);
}
- protected Pipeline getPipeline() {
+ Pipeline getPipeline() {
return getContainer().getPipeline();
}
@@ -660,7 +673,7 @@
* @throws IOException if an input/output error occurs
*/
private void doUnload() throws IOException {
- QueryService querySvc = sessionCache.getCache().getQueryService();
+ QueryService querySvc = getSessionCache().getCache().getQueryService();
Context context = getTheContext();
if (context == null) {
@@ -707,9 +720,9 @@
ObjectOutputStream oos = null;
boolean error = false;
try {
- fos = new FileOutputStream(store.getAbsolutePath());
- bos = new BufferedOutputStream(fos);
- oos = new ObjectOutputStream(bos);
+ fos = getFileOutputStream(store);
+ bos = getBufferedOutputStream(fos);
+ oos = getObjectOutputStream(bos);
} catch (IOException e) {
error = true;
getLogger().error("Exception unloading sessions", e);
@@ -755,7 +768,7 @@
if (getLogger().isDebugEnabled())
getLogger().debug("Unloading " + list.size() + " sessions");
try {
- oos.writeObject(list.size());
+ writeToObjectOutputStream(oos, list);
for (DeltaSessionInterface session : list) {
if (session instanceof StandardSession) {
StandardSession standardSession = (StandardSession) session;
@@ -830,8 +843,8 @@
Loader loader = null;
ClassLoader classLoader = null;
try {
- fis = new FileInputStream(store.getAbsolutePath());
- bis = new BufferedInputStream(fis);
+ fis = getFileInputStream(store);
+ bis = getBufferedInputStream(fis);
if (getTheContext() != null) {
loader = getTheContext().getLoader();
}
@@ -847,7 +860,7 @@
if (getLogger().isDebugEnabled()) {
getLogger().debug("Creating standard object input stream");
}
- ois = new ObjectInputStream(bis);
+ ois = getObjectInputStream(bis);
}
} catch (FileNotFoundException e) {
if (getLogger().isDebugEnabled()) {
@@ -871,7 +884,7 @@
// Load the previously unloaded active sessions
try {
- int n = (Integer) ois.readObject();
+ int n = getSessionCountFromObjectInputStream(ois);
if (getLogger().isDebugEnabled()) {
getLogger().debug("Loading " + n + " persisted sessions");
}
@@ -932,16 +945,57 @@
* Return a File object representing the pathname to our persistence file, if any.
*/
private File sessionStore(String ctxPath) {
- String storeDir = System.getProperty("catalina.base");
+ String storeDir = getSystemPropertyValue(catalinaBaseSystemProperty);
if (storeDir == null || storeDir.isEmpty()) {
- storeDir = System.getProperty("java.io.tmpdir");
+ storeDir = getSystemPropertyValue(javaTempDirSystemProperty);
} else {
- storeDir += System.getProperty("file.separator") + "temp";
+ storeDir += getSystemPropertyValue(fileSeparatorSystemProperty) + "temp";
}
+ return getFileAtPath(storeDir, ctxPath);
+ }
+
+ String getSystemPropertyValue(String propertyKey) {
+ return System.getProperty(propertyKey);
+ }
+
+ File getFileAtPath(String storeDir, String ctxPath) {
return (new File(storeDir, ctxPath.replaceAll("/", "_") + ".sessions.ser"));
}
+ FileInputStream getFileInputStream(File file) throws FileNotFoundException {
+ return new FileInputStream(file.getAbsolutePath());
+ }
+
+ BufferedInputStream getBufferedInputStream(FileInputStream fis) {
+ return new BufferedInputStream(fis);
+ }
+
+ ObjectInputStream getObjectInputStream(BufferedInputStream bis) throws IOException {
+ return new ObjectInputStream(bis);
+ }
+
+ FileOutputStream getFileOutputStream(File file) throws FileNotFoundException {
+ return new FileOutputStream(file.getAbsolutePath());
+ }
+
+ BufferedOutputStream getBufferedOutputStream(FileOutputStream fos) {
+ return new BufferedOutputStream(fos);
+ }
+
+ ObjectOutputStream getObjectOutputStream(BufferedOutputStream bos) throws IOException {
+ return new ObjectOutputStream(bos);
+ }
+
+ void writeToObjectOutputStream(ObjectOutputStream oos, List listToWrite) throws IOException {
+ oos.writeObject(listToWrite.size());
+ }
+
+ int getSessionCountFromObjectInputStream(ObjectInputStream ois)
+ throws IOException, ClassNotFoundException {
+ return (Integer) ois.readObject();
+ }
+
@Override
public String toString() {
return getClass().getSimpleName() + "[" + "container="
diff --git a/extensions/geode-modules/src/main/java/org/apache/geode/modules/session/catalina/PeerToPeerSessionCache.java b/extensions/geode-modules/src/main/java/org/apache/geode/modules/session/catalina/PeerToPeerSessionCache.java
index 7d4b941..d5031c1 100644
--- a/extensions/geode-modules/src/main/java/org/apache/geode/modules/session/catalina/PeerToPeerSessionCache.java
+++ b/extensions/geode-modules/src/main/java/org/apache/geode/modules/session/catalina/PeerToPeerSessionCache.java
@@ -24,6 +24,7 @@
import org.apache.geode.cache.RegionFactory;
import org.apache.geode.cache.RegionShortcut;
import org.apache.geode.cache.execute.Execution;
+import org.apache.geode.cache.execute.Function;
import org.apache.geode.cache.execute.FunctionService;
import org.apache.geode.cache.execute.ResultCollector;
import org.apache.geode.modules.session.catalina.callback.LocalSessionCacheLoader;
@@ -87,12 +88,12 @@
ResultCollector collector = null;
if (regionAttributesID.startsWith("partition")) {
// Execute the partitioned touch function on the primary server(s)
- Execution execution = FunctionService.onRegion(getSessionRegion()).withFilter(sessionIds);
+ Execution execution = getExecutionForFunctionOnRegionWithFilter(sessionIds);
collector = execution.execute(TouchPartitionedRegionEntriesFunction.ID);
} else {
// Execute the member touch function on all the server(s)
- Execution execution = FunctionService.onMembers()
- .setArguments(new Object[] {this.sessionRegion.getFullPath(), sessionIds});
+ Execution execution = getExecutionForFunctionOnMembersWithArguments(
+ new Object[] {this.sessionRegion.getFullPath(), sessionIds});
collector = execution.execute(TouchReplicatedRegionEntriesFunction.ID);
}
@@ -105,6 +106,7 @@
}
}
+
@Override
public boolean isPeerToPeer() {
return true;
@@ -142,13 +144,13 @@
private void registerFunctions() {
// Register the touch partitioned region entries function if it is not already registered
- if (!FunctionService.isRegistered(TouchPartitionedRegionEntriesFunction.ID)) {
- FunctionService.registerFunction(new TouchPartitionedRegionEntriesFunction());
+ if (!isFunctionRegistered(TouchPartitionedRegionEntriesFunction.ID)) {
+ registerFunctionWithFunctionService(new TouchPartitionedRegionEntriesFunction());
}
// Register the touch replicated region entries function if it is not already registered
- if (!FunctionService.isRegistered(TouchReplicatedRegionEntriesFunction.ID)) {
- FunctionService.registerFunction(new TouchReplicatedRegionEntriesFunction());
+ if (!isFunctionRegistered(TouchReplicatedRegionEntriesFunction.ID)) {
+ registerFunctionWithFunctionService(new TouchReplicatedRegionEntriesFunction());
}
}
@@ -164,7 +166,7 @@
Region region = this.cache.getRegion(getSessionManager().getRegionName());
if (region == null) {
// Create the region
- region = RegionHelper.createRegion((Cache) getCache(), configuration);
+ region = createRegionUsingHelper(configuration);
if (getSessionManager().getLogger().isDebugEnabled()) {
getSessionManager().getLogger().debug("Created new session region: " + region);
}
@@ -173,13 +175,21 @@
if (getSessionManager().getLogger().isDebugEnabled()) {
getSessionManager().getLogger().debug("Retrieved existing session region: " + region);
}
- RegionHelper.validateRegion((Cache) getCache(), configuration, region);
+ validateRegionUsingRegionhelper(configuration, region);
}
// Set the session region
this.sessionRegion = region;
}
+ void validateRegionUsingRegionhelper(RegionConfiguration configuration, Region region) {
+ RegionHelper.validateRegion((Cache) getCache(), configuration, region);
+ }
+
+ Region createRegionUsingHelper(RegionConfiguration configuration) {
+ return RegionHelper.createRegion((Cache) getCache(), configuration);
+ }
+
private Region<String, HttpSession> createOrRetrieveLocalRegion() {
// Attempt to retrieve the fronting region
String frontingRegionName = this.sessionRegion.getName() + "_local";
@@ -215,4 +225,21 @@
}
return frontingRegion;
}
+
+ // Helper methods added to improve unit testing of class
+ void registerFunctionWithFunctionService(Function function) {
+ FunctionService.registerFunction(function);
+ }
+
+ boolean isFunctionRegistered(String id) {
+ return FunctionService.isRegistered(id);
+ }
+
+ Execution getExecutionForFunctionOnRegionWithFilter(Set<String> sessionIds) {
+ return FunctionService.onRegion(getSessionRegion()).withFilter(sessionIds);
+ }
+
+ Execution getExecutionForFunctionOnMembersWithArguments(Object[] arguments) {
+ return FunctionService.onMembers().setArguments(arguments);
+ }
}
diff --git a/extensions/geode-modules/src/main/java/org/apache/geode/modules/util/TouchPartitionedRegionEntriesFunction.java b/extensions/geode-modules/src/main/java/org/apache/geode/modules/util/TouchPartitionedRegionEntriesFunction.java
index 4f4049e..2fbeec5 100644
--- a/extensions/geode-modules/src/main/java/org/apache/geode/modules/util/TouchPartitionedRegionEntriesFunction.java
+++ b/extensions/geode-modules/src/main/java/org/apache/geode/modules/util/TouchPartitionedRegionEntriesFunction.java
@@ -47,7 +47,7 @@
Cache cache = context.getCache();
// Get local (primary) data for the context
- Region primaryDataSet = PartitionRegionHelper.getLocalDataForContext(rfc);
+ Region primaryDataSet = getLocalDataForContextViaRegionHelper(rfc);
if (cache.getLogger().fineEnabled()) {
String builder = "Function " + ID + " received request to touch "
@@ -96,4 +96,9 @@
@Override
public void fromData(DataInput in) {}
+
+ // Helper methods added to improve unit testing of class
+ Region getLocalDataForContextViaRegionHelper(RegionFunctionContext rfc) {
+ return PartitionRegionHelper.getLocalDataForContext(rfc);
+ }
}