From 8dc42601b7d67af322e2494da00d4c7b149ebf75 Mon Sep 17 00:00:00 2001 From: John Blum Date: Mon, 15 Jul 2019 16:31:16 -0700 Subject: [PATCH] DATAGEODE-197 - Prepare Region configuration using SDG FactoryBeans to accept AEQ and GatewaySender IDs for association. --- .../data/gemfire/LocalRegionFactoryBean.java | 18 ++- .../gemfire/PartitionedRegionFactoryBean.java | 7 +- .../data/gemfire/PeerRegionFactoryBean.java | 118 +++++++++--------- .../gemfire/ReplicatedRegionFactoryBean.java | 7 +- .../client/ClientRegionFactoryBean.java | 12 +- .../data/gemfire/util/RegionUtils.java | 44 ++++++- .../gemfire/LocalRegionFactoryBeanTest.java | 26 ++-- .../PartitionedRegionFactoryBeanTest.java | 21 ++-- .../ReplicatedRegionFactoryBeanTest.java | 21 ++-- .../gemfire/util/RegionUtilsUnitTests.java | 90 ++++++++++++- 10 files changed, 247 insertions(+), 117 deletions(-) diff --git a/src/main/java/org/springframework/data/gemfire/LocalRegionFactoryBean.java b/src/main/java/org/springframework/data/gemfire/LocalRegionFactoryBean.java index b8eda88a..50943dd3 100644 --- a/src/main/java/org/springframework/data/gemfire/LocalRegionFactoryBean.java +++ b/src/main/java/org/springframework/data/gemfire/LocalRegionFactoryBean.java @@ -15,9 +15,13 @@ */ package org.springframework.data.gemfire; +import static org.springframework.data.gemfire.util.RuntimeExceptionFactory.newIllegalArgumentException; +import static org.springframework.data.gemfire.util.RuntimeExceptionFactory.newUnsupportedOperationException; + import org.apache.geode.cache.DataPolicy; import org.apache.geode.cache.RegionFactory; import org.apache.geode.cache.Scope; + import org.springframework.util.Assert; /** @@ -28,18 +32,21 @@ public class LocalRegionFactoryBean extends PeerRegionFactoryBean { @Override public void setScope(Scope scope) { - throw new UnsupportedOperationException("Setting the Scope on Local Regions is not allowed."); + throw newUnsupportedOperationException("Setting the Scope on Local Regions is not allowed"); } @Override public void afterPropertiesSet() throws Exception { + super.setScope(Scope.LOCAL); super.afterPropertiesSet(); } @Override protected void resolveDataPolicy(RegionFactory regionFactory, Boolean persistent, DataPolicy dataPolicy) { + if (dataPolicy == null || DataPolicy.NORMAL.equals(dataPolicy)) { + // NOTE this is safe since a LOCAL Scoped NORMAL Region requiring persistence can be satisfied with // PERSISTENT_REPLICATE, per the RegionShortcut.LOCAL_PERSISTENT DataPolicy resolvedDataPolicy = (isPersistent() ? DataPolicy.PERSISTENT_REPLICATE : DataPolicy.NORMAL); @@ -48,6 +55,7 @@ public class LocalRegionFactoryBean extends PeerRegionFactoryBean { setDataPolicy(resolvedDataPolicy); } else if (DataPolicy.PRELOADED.equals(dataPolicy)) { + // NOTE this is safe since a LOCAL Scoped PRELOADED Region requiring persistence can be satisfied with // PERSISTENT_REPLICATE, per the RegionShortcut.LOCAL_PERSISTENT DataPolicy resolvedDataPolicy = (isPersistent() ? DataPolicy.PERSISTENT_REPLICATE : DataPolicy.PRELOADED); @@ -57,12 +65,12 @@ public class LocalRegionFactoryBean extends PeerRegionFactoryBean { } else if (DataPolicy.PERSISTENT_REPLICATE.equals(dataPolicy) && RegionShortcutWrapper.valueOf(getShortcut()).isPersistent()) { + regionFactory.setDataPolicy(dataPolicy); setDataPolicy(dataPolicy); } else { - throw new IllegalArgumentException(String.format("Data Policy '%1$s' is not supported for Local Regions.", - dataPolicy)); + throw newIllegalArgumentException("Data Policy [%s] is not supported for Local Regions", dataPolicy); } } @@ -80,14 +88,14 @@ public class LocalRegionFactoryBean extends PeerRegionFactoryBean { */ @Override protected void resolveDataPolicy(RegionFactory regionFactory, Boolean persistent, String dataPolicy) { + DataPolicy resolvedDataPolicy = null; if (dataPolicy != null) { resolvedDataPolicy = new DataPolicyConverter().convert(dataPolicy); - Assert.notNull(resolvedDataPolicy, String.format("Data Policy '%1$s' is invalid.", dataPolicy)); + Assert.notNull(resolvedDataPolicy, String.format("Data Policy [%s] is invalid", dataPolicy)); } resolveDataPolicy(regionFactory, persistent, resolvedDataPolicy); } - } diff --git a/src/main/java/org/springframework/data/gemfire/PartitionedRegionFactoryBean.java b/src/main/java/org/springframework/data/gemfire/PartitionedRegionFactoryBean.java index 6c7c8c99..d792b5d6 100644 --- a/src/main/java/org/springframework/data/gemfire/PartitionedRegionFactoryBean.java +++ b/src/main/java/org/springframework/data/gemfire/PartitionedRegionFactoryBean.java @@ -17,6 +17,7 @@ package org.springframework.data.gemfire; import org.apache.geode.cache.DataPolicy; import org.apache.geode.cache.RegionFactory; + import org.springframework.data.gemfire.util.RegionUtils; import org.springframework.util.Assert; @@ -30,13 +31,13 @@ public class PartitionedRegionFactoryBean extends PeerRegionFactoryBean regionFactory, Boolean persistent, DataPolicy dataPolicy) { if (dataPolicy == null) { - dataPolicy = (isPersistent() ? DataPolicy.PERSISTENT_PARTITION : DataPolicy.PARTITION); + dataPolicy = isPersistent() ? DataPolicy.PERSISTENT_PARTITION : DataPolicy.PARTITION; } else { // Validate that the user-defined Data Policy matches the appropriate Spring GemFire XML namespace // configuration meta-data element for Region (i.e. )! Assert.isTrue(dataPolicy.withPartitioning(), String.format( - "Data Policy '%1$s' is not supported in Partitioned Regions.", dataPolicy)); + "Data Policy [%s] is not supported in Partitioned Regions.", dataPolicy)); } // Validate the data-policy and persistent attributes are compatible when specified! @@ -53,7 +54,7 @@ public class PartitionedRegionFactoryBean extends PeerRegionFactoryBean extends ConfigurableRegionFactoryBean - implements EvictingRegionFactoryBean, ExpiringRegionFactoryBean, DisposableBean, SmartLifecycle { + implements DisposableBean, EvictingRegionFactoryBean, ExpiringRegionFactoryBean, SmartLifecycle { - private boolean close = true; + private boolean close = false; private boolean destroy = false; private boolean running; @@ -148,7 +148,7 @@ public abstract class PeerRegionFactoryBean extends ConfigurableRegionFact * @see org.apache.geode.cache.Region */ @Override - protected Region createRegion(GemFireCache gemfireCache, String regionName) throws Exception { + protected Region createRegion(GemFireCache gemfireCache, String regionName) { applyRegionConfigurers(regionName); @@ -176,13 +176,14 @@ public abstract class PeerRegionFactoryBean extends ConfigurableRegionFact return Optional.ofNullable(parentRegion) .map(parent -> { - logInfo("Creating Subregion [%1$s] with parent Region [%2$s]", - regionName, parent.getName()); - return regionFactory.createSubregion(parent, regionName); + logInfo("Creating Subregion [%1$s] with parent Region [%2$s]", regionName, parent.getName()); + + return regionFactory.createSubregion(parent, regionName); }) .orElseGet(() -> { - logInfo("Created Region [%1$s]", regionName); + + logInfo("Created Region [%s]", regionName); return regionFactory.create(regionName); }); @@ -191,8 +192,8 @@ public abstract class PeerRegionFactoryBean extends ConfigurableRegionFact private Cache resolveCache(GemFireCache gemfireCache) { return Optional.ofNullable(gemfireCache) - .filter(cache -> cache instanceof Cache) - .map(cache -> (Cache) cache) + .filter(Cache.class::isInstance) + .map(Cache.class::cast) .orElseThrow(() -> newIllegalArgumentException("Peer Cache is required")); } @@ -283,6 +284,8 @@ public abstract class PeerRegionFactoryBean extends ConfigurableRegionFact Optional.ofNullable(this.keyConstraint).ifPresent(regionFactory::setKeyConstraint); + Optional.ofNullable(this.offHeap).ifPresent(regionFactory::setOffHeap); + Optional.ofNullable(this.regionIdleTimeout).ifPresent(regionFactory::setRegionIdleTimeout); Optional.ofNullable(this.regionTimeToLive).ifPresent(regionFactory::setRegionTimeToLive); @@ -306,9 +309,6 @@ public abstract class PeerRegionFactoryBean extends ConfigurableRegionFact * @see org.apache.geode.cache.RegionFactory */ protected RegionFactory postProcess(RegionFactory regionFactory) { - - Optional.ofNullable(this.offHeap).ifPresent(regionFactory::setOffHeap); - return regionFactory; } @@ -368,7 +368,6 @@ public abstract class PeerRegionFactoryBean extends ConfigurableRegionFact * @see org.apache.geode.cache.RegionAttributes * @see org.apache.geode.cache.RegionFactory */ - @SuppressWarnings("unchecked") protected RegionFactory mergeRegionAttributes(RegionFactory regionFactory, RegionAttributes regionAttributes) { @@ -459,6 +458,33 @@ public abstract class PeerRegionFactoryBean extends ConfigurableRegionFact } } + private boolean isDiskStoreConfigurationAllowed() { + + boolean allow = StringUtils.hasText(this.diskStoreName); + + allow &= getDataPolicy().withPersistence() + || (getAttributes() != null && getAttributes().getEvictionAttributes() != null + && EvictionAction.OVERFLOW_TO_DISK.equals(attributes.getEvictionAttributes().getAction())); + + return allow; + } + + /* + * (non-Javadoc) + * + * This method is not part of the PeerRegionFactoryBean API and is strictly used for testing purposes! + * + * NOTE unfortunately, must resort to using a GemFire internal class, ugh! + * + * @see org.apache.geode.internal.cache.UserSpecifiedRegionAttributes#hasEvictionAttributes + */ + + boolean isUserSpecifiedEvictionAttributes(final RegionAttributes regionAttributes) { + + return regionAttributes instanceof UserSpecifiedRegionAttributes + && ((UserSpecifiedRegionAttributes) regionAttributes).hasEvictionAttributes(); + } + /* * (non-Javadoc) * @@ -471,30 +497,17 @@ public abstract class PeerRegionFactoryBean extends ConfigurableRegionFact org.apache.geode.cache.AttributesFactory.validateAttributes(regionAttributes); } - /* - * (non-Javadoc) + /** + * Returns true when the user explicitly specified a value for the persistent attribute and it is false. If the + * persistent attribute was not explicitly specified, then the persistence setting is implicitly undefined + * and will be determined by the Data Policy. * - * This method is not part of the PeerRegionFactoryBean API and is strictly used for testing purposes! - * - * NOTE unfortunately, must resort to using a GemFire internal class, ugh! - * - * @see org.apache.geode.internal.cache.UserSpecifiedRegionAttributes#hasEvictionAttributes + * @return true when the user specified an explicit value for the persistent attribute and it is false; + * false otherwise. + * @see #isPersistent() */ - boolean isUserSpecifiedEvictionAttributes(final RegionAttributes regionAttributes) { - return (regionAttributes instanceof UserSpecifiedRegionAttributes - && ((UserSpecifiedRegionAttributes) regionAttributes).hasEvictionAttributes()); - } - - private boolean isDiskStoreConfigurationAllowed() { - - boolean allow = StringUtils.hasText(this.diskStoreName); - - allow &= (getDataPolicy().withPersistence() - || (getAttributes() != null - && getAttributes().getEvictionAttributes() != null - && EvictionAction.OVERFLOW_TO_DISK.equals(attributes.getEvictionAttributes().getAction()))); - - return allow; + protected boolean isNotPersistent() { + return Boolean.FALSE.equals(this.persistent); } /** @@ -507,20 +520,7 @@ public abstract class PeerRegionFactoryBean extends ConfigurableRegionFact * @see #isNotPersistent() */ protected boolean isPersistent() { - return Boolean.TRUE.equals(persistent); - } - - /** - * Returns true when the user explicitly specified a value for the persistent attribute and it is false. If the - * persistent attribute was not explicitly specified, then the persistence setting is implicitly undefined - * and will be determined by the Data Policy. - * - * @return true when the user specified an explicit value for the persistent attribute and it is false; - * false otherwise. - * @see #isPersistent() - */ - protected boolean isNotPersistent() { - return Boolean.FALSE.equals(persistent); + return Boolean.TRUE.equals(this.persistent); } /** @@ -575,7 +575,8 @@ public abstract class PeerRegionFactoryBean extends ConfigurableRegionFact DataPolicy regionAttributesDataPolicy = getDataPolicy(getAttributes(), DataPolicy.DEFAULT); DataPolicy resolvedDataPolicy = isPersistent() && DataPolicy.DEFAULT.equals(regionAttributesDataPolicy) - ? DataPolicy.PERSISTENT_REPLICATE : regionAttributesDataPolicy; + ? DataPolicy.PERSISTENT_REPLICATE + : regionAttributesDataPolicy; RegionUtils.assertDataPolicyAndPersistentAttributeAreCompatible(resolvedDataPolicy, this.persistent); @@ -585,7 +586,10 @@ public abstract class PeerRegionFactoryBean extends ConfigurableRegionFact } private DataPolicy getDataPolicy(RegionAttributes regionAttributes, DataPolicy defaultDataPolicy) { - return Optional.ofNullable(regionAttributes).map(RegionAttributes::getDataPolicy).orElse(defaultDataPolicy); + + return Optional.ofNullable(regionAttributes) + .map(RegionAttributes::getDataPolicy) + .orElse(defaultDataPolicy); } /** @@ -600,15 +604,9 @@ public abstract class PeerRegionFactoryBean extends ConfigurableRegionFact public void destroy() throws Exception { Optional.ofNullable(getObject()).ifPresent(region -> { - if (this.close) { - if (!region.getRegionService().isClosed()) { - try { - region.close(); - } - catch (Exception ignore) { - } - } + if (this.close && RegionUtils.isCloseable(region)) { + RegionUtils.close(region); } if (this.destroy) { diff --git a/src/main/java/org/springframework/data/gemfire/ReplicatedRegionFactoryBean.java b/src/main/java/org/springframework/data/gemfire/ReplicatedRegionFactoryBean.java index 3d011202..35464256 100644 --- a/src/main/java/org/springframework/data/gemfire/ReplicatedRegionFactoryBean.java +++ b/src/main/java/org/springframework/data/gemfire/ReplicatedRegionFactoryBean.java @@ -17,6 +17,7 @@ package org.springframework.data.gemfire; import org.apache.geode.cache.DataPolicy; import org.apache.geode.cache.RegionFactory; + import org.springframework.data.gemfire.util.RegionUtils; import org.springframework.util.Assert; @@ -30,7 +31,7 @@ public class ReplicatedRegionFactoryBean extends PeerRegionFactoryBean regionFactory, Boolean persistent, DataPolicy dataPolicy) { if (dataPolicy == null) { - dataPolicy = (isPersistent() ? DataPolicy.PERSISTENT_REPLICATE : DataPolicy.REPLICATE); + dataPolicy = isPersistent() ? DataPolicy.PERSISTENT_REPLICATE : DataPolicy.REPLICATE; } else if (DataPolicy.EMPTY.equals(dataPolicy)) { dataPolicy = DataPolicy.EMPTY; @@ -39,7 +40,7 @@ public class ReplicatedRegionFactoryBean extends PeerRegionFactoryBean)! Assert.isTrue(dataPolicy.withReplication(), String.format( - "Data Policy '%1$s' is not supported in Replicated Regions.", dataPolicy)); + "Data Policy [%s] is not supported in Replicated Regions.", dataPolicy)); } // Validate that the data-policy and persistent attributes are compatible when both are specified! @@ -56,7 +57,7 @@ public class ReplicatedRegionFactoryBean extends PeerRegionFactoryBean extends ConfigurableRegionFactoryBean return clientRegionFactory.createSubregion(parent, regionName); } else { + logInfo("Creating client Region [%s]", regionName); + return clientRegionFactory.create(regionName); } } @@ -427,14 +429,8 @@ public class ClientRegionFactoryBean extends ConfigurableRegionFactoryBean Optional.ofNullable(getObject()).ifPresent(region -> { - if (isClose()) { - if (!region.getRegionService().isClosed()) { - try { - region.close(); - } - catch (Exception ignore) { - } - } + if (isClose() && RegionUtils.isCloseable(region)) { + RegionUtils.close(region); } if (isDestroy()) { diff --git a/src/main/java/org/springframework/data/gemfire/util/RegionUtils.java b/src/main/java/org/springframework/data/gemfire/util/RegionUtils.java index e5630dd4..439d8c6c 100644 --- a/src/main/java/org/springframework/data/gemfire/util/RegionUtils.java +++ b/src/main/java/org/springframework/data/gemfire/util/RegionUtils.java @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package org.springframework.data.gemfire.util; import java.util.Optional; @@ -22,6 +21,7 @@ import org.apache.geode.cache.DataPolicy; import org.apache.geode.cache.Region; import org.apache.geode.cache.RegionAttributes; import org.apache.geode.cache.client.ClientRegionShortcut; + import org.springframework.data.gemfire.client.ClientRegionShortcutWrapper; import org.springframework.lang.NonNull; import org.springframework.lang.Nullable; @@ -86,6 +86,33 @@ public abstract class RegionUtils extends CacheUtils { } } + /** + * Safely closes the target {@link Region}. + * + * @param region {@link Region} to close + * @return a boolean indicating whether the {@link Region} was successfully closed or not. + * @see org.apache.geode.cache.Region#close + */ + public static boolean close(Region region) { + + try { + + region.close(); + + return true; + } + catch (Throwable ignore) { + return false; + } + } + + /** + * Determines whether the target {@link Region} is a {@literal client} {@link Region}. + * + * @param region {@link Region} to evaluate. + * @return a boolean indicating whether the target {@link Region} is a {@literal client} {@link Region}. + * @see org.apache.geode.cache.Region + */ public static boolean isClient(Region region) { return Optional.ofNullable(region) @@ -95,6 +122,21 @@ public abstract class RegionUtils extends CacheUtils { .isPresent(); } + /** + * Determines whether the given {@link Region} is closeable. + * + * @param region {@link Region} to evaluate. + * @return a boolean value indicating whether the {@link Region} is closeable or not. + * @see org.apache.geode.cache.Region + */ + public static boolean isCloseable(Region region) { + + return Optional.ofNullable(region) + .map(Region::getRegionService) + .filter(regionService -> !regionService.isClosed()) + .isPresent(); + } + @Nullable public static String toRegionName(@Nullable Region region) { return Optional.ofNullable(region).map(Region::getName).orElse(null); diff --git a/src/test/java/org/springframework/data/gemfire/LocalRegionFactoryBeanTest.java b/src/test/java/org/springframework/data/gemfire/LocalRegionFactoryBeanTest.java index d78d92c1..0ee9b804 100644 --- a/src/test/java/org/springframework/data/gemfire/LocalRegionFactoryBeanTest.java +++ b/src/test/java/org/springframework/data/gemfire/LocalRegionFactoryBeanTest.java @@ -13,31 +13,35 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package org.springframework.data.gemfire; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; -import static org.mockito.Matchers.eq; +import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; +import org.junit.Test; + import org.apache.geode.cache.DataPolicy; import org.apache.geode.cache.Region; import org.apache.geode.cache.RegionFactory; import org.apache.geode.cache.RegionShortcut; -import org.junit.Test; + import org.springframework.data.gemfire.test.support.AbstractRegionFactoryBeanTests; /** - * The PartitionedRegionFactoryBeanTest class is a test suite of test cases testing the component functionality - * and correct behavior of the PartitionedRegionFactoryBean class. + * Unit Tests for {@link LocalRegionFactoryBean}. * * @author David Turanski * @author John Blum * @see org.mockito.Mockito * @see org.junit.Test + * @see org.apache.geode.cache.DataPolicy + * @see org.apache.geode.cache.Region + * @see org.apache.geode.cache.RegionFactory + * @see org.apache.geode.cache.RegionShortcut * @see org.springframework.data.gemfire.LocalRegionFactoryBean * @since 1.3.x */ @@ -133,7 +137,7 @@ public class LocalRegionFactoryBeanTest extends AbstractRegionFactoryBeanTests { factoryBean.resolveDataPolicy(mockRegionFactory, null, " "); } catch (IllegalArgumentException e) { - assertEquals("Data Policy ' ' is invalid.", e.getMessage()); + assertEquals("Data Policy [ ] is invalid", e.getMessage()); throw e; } finally { @@ -153,7 +157,7 @@ public class LocalRegionFactoryBeanTest extends AbstractRegionFactoryBeanTests { factoryBean.resolveDataPolicy(mockRegionFactory, null, ""); } catch (IllegalArgumentException e) { - assertEquals("Data Policy '' is invalid.", e.getMessage()); + assertEquals("Data Policy [] is invalid", e.getMessage()); throw e; } finally { @@ -173,7 +177,7 @@ public class LocalRegionFactoryBeanTest extends AbstractRegionFactoryBeanTests { factoryBean.resolveDataPolicy(mockRegionFactory, null, "INVALID_DATA_POLICY_NAME"); } catch (IllegalArgumentException e) { - assertEquals("Data Policy 'INVALID_DATA_POLICY_NAME' is invalid.", e.getMessage()); + assertEquals("Data Policy [INVALID_DATA_POLICY_NAME] is invalid", e.getMessage()); throw e; } finally { @@ -193,7 +197,7 @@ public class LocalRegionFactoryBeanTest extends AbstractRegionFactoryBeanTests { factoryBean.resolveDataPolicy(mockRegionFactory, null, "PARTITION"); } catch (IllegalArgumentException e) { - assertEquals("Data Policy 'PARTITION' is not supported for Local Regions.", e.getMessage()); + assertEquals("Data Policy [PARTITION] is not supported for Local Regions", e.getMessage()); throw e; } finally { @@ -278,7 +282,7 @@ public class LocalRegionFactoryBeanTest extends AbstractRegionFactoryBeanTests { factoryBean.resolveDataPolicy(mockRegionFactory, null, DataPolicy.PERSISTENT_REPLICATE); } catch (IllegalArgumentException expected) { - assertEquals("Data Policy 'PERSISTENT_REPLICATE' is not supported for Local Regions.", + assertEquals("Data Policy [PERSISTENT_REPLICATE] is not supported for Local Regions", expected.getMessage()); throw expected; } @@ -300,7 +304,7 @@ public class LocalRegionFactoryBeanTest extends AbstractRegionFactoryBeanTests { factoryBean.resolveDataPolicy(mockRegionFactory, true, DataPolicy.PERSISTENT_REPLICATE); } catch (IllegalArgumentException expected) { - assertEquals("Data Policy 'PERSISTENT_REPLICATE' is not supported for Local Regions.", + assertEquals("Data Policy [PERSISTENT_REPLICATE] is not supported for Local Regions", expected.getMessage()); throw expected; } diff --git a/src/test/java/org/springframework/data/gemfire/PartitionedRegionFactoryBeanTest.java b/src/test/java/org/springframework/data/gemfire/PartitionedRegionFactoryBeanTest.java index 28ddcd24..607b866b 100644 --- a/src/test/java/org/springframework/data/gemfire/PartitionedRegionFactoryBeanTest.java +++ b/src/test/java/org/springframework/data/gemfire/PartitionedRegionFactoryBeanTest.java @@ -13,29 +13,28 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package org.springframework.data.gemfire; import static org.junit.Assert.assertEquals; -import static org.mockito.Matchers.eq; +import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; -import org.apache.geode.cache.DataPolicy; -import org.apache.geode.cache.RegionFactory; import org.junit.Test; +import org.apache.geode.cache.DataPolicy; +import org.apache.geode.cache.RegionFactory; + /** - * The PartitionedRegionFactoryBeanTest class is a test suite of test cases testing the component functionality - * and correct behavior of the PartitionedRegionFactoryBean class. + * Unit Tests for {@link PartitionedRegionFactoryBean}. * * @author John Blum * @see org.junit.Test * @see org.mockito.Mockito - * @see org.springframework.data.gemfire.PartitionedRegionFactoryBean * @see org.apache.geode.cache.DataPolicy * @see org.apache.geode.cache.RegionFactory + * @see org.springframework.data.gemfire.PartitionedRegionFactoryBean * @since 1.3.3 */ @SuppressWarnings("unchecked") @@ -78,7 +77,7 @@ public class PartitionedRegionFactoryBeanTest { factoryBean.resolveDataPolicy(mockRegionFactory, null, " "); } catch (IllegalArgumentException e) { - assertEquals("Data Policy ' ' is invalid.", e.getMessage()); + assertEquals("Data Policy [ ] is invalid.", e.getMessage()); throw e; } finally { @@ -97,7 +96,7 @@ public class PartitionedRegionFactoryBeanTest { factoryBean.resolveDataPolicy(mockRegionFactory, null, ""); } catch (IllegalArgumentException e) { - assertEquals("Data Policy '' is invalid.", e.getMessage()); + assertEquals("Data Policy [] is invalid.", e.getMessage()); throw e; } finally { @@ -116,7 +115,7 @@ public class PartitionedRegionFactoryBeanTest { factoryBean.resolveDataPolicy(mockRegionFactory, null, "INVALID_DATA_POLICY_NAME"); } catch (IllegalArgumentException e) { - assertEquals("Data Policy 'INVALID_DATA_POLICY_NAME' is invalid.", e.getMessage()); + assertEquals("Data Policy [INVALID_DATA_POLICY_NAME] is invalid.", e.getMessage()); throw e; } finally { @@ -134,7 +133,7 @@ public class PartitionedRegionFactoryBeanTest { factoryBean.resolveDataPolicy(mockRegionFactory, null, "REPLICATE"); } catch (IllegalArgumentException e) { - assertEquals("Data Policy 'REPLICATE' is not supported in Partitioned Regions.", e.getMessage()); + assertEquals("Data Policy [REPLICATE] is not supported in Partitioned Regions.", e.getMessage()); throw e; } finally { diff --git a/src/test/java/org/springframework/data/gemfire/ReplicatedRegionFactoryBeanTest.java b/src/test/java/org/springframework/data/gemfire/ReplicatedRegionFactoryBeanTest.java index 7f745cd2..ce74fcbf 100644 --- a/src/test/java/org/springframework/data/gemfire/ReplicatedRegionFactoryBeanTest.java +++ b/src/test/java/org/springframework/data/gemfire/ReplicatedRegionFactoryBeanTest.java @@ -13,29 +13,28 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package org.springframework.data.gemfire; import static org.junit.Assert.assertEquals; -import static org.mockito.Matchers.eq; +import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; -import org.apache.geode.cache.DataPolicy; -import org.apache.geode.cache.RegionFactory; import org.junit.Test; +import org.apache.geode.cache.DataPolicy; +import org.apache.geode.cache.RegionFactory; + /** - * The ReplicatedRegionFactoryBeanTest class is a test suite of test cases testing the component functionality - * and correct behavior of the ReplicatedRegionFactoryBean class. + * Unit Tests for {@link ReplicatedRegionFactoryBean}. * * @author John Blum * @see org.junit.Test * @see org.mockito.Mockito - * @see org.springframework.data.gemfire.ReplicatedRegionFactoryBean * @see org.apache.geode.cache.DataPolicy * @see org.apache.geode.cache.RegionFactory + * @see org.springframework.data.gemfire.ReplicatedRegionFactoryBean * @since 1.3.3 */ @SuppressWarnings("unchecked") @@ -78,7 +77,7 @@ public class ReplicatedRegionFactoryBeanTest { factoryBean.resolveDataPolicy(mockRegionFactory, null, " "); } catch (IllegalArgumentException e) { - assertEquals("Data Policy ' ' is invalid.", e.getMessage()); + assertEquals("Data Policy [ ] is invalid.", e.getMessage()); throw e; } finally { @@ -97,7 +96,7 @@ public class ReplicatedRegionFactoryBeanTest { factoryBean.resolveDataPolicy(mockRegionFactory, null, ""); } catch (IllegalArgumentException e) { - assertEquals("Data Policy '' is invalid.", e.getMessage()); + assertEquals("Data Policy [] is invalid.", e.getMessage()); throw e; } finally { @@ -116,7 +115,7 @@ public class ReplicatedRegionFactoryBeanTest { factoryBean.resolveDataPolicy(mockRegionFactory, null, "INVALID_DATA_POLICY_NAME"); } catch (IllegalArgumentException e) { - assertEquals("Data Policy 'INVALID_DATA_POLICY_NAME' is invalid.", e.getMessage()); + assertEquals("Data Policy [INVALID_DATA_POLICY_NAME] is invalid.", e.getMessage()); throw e; } finally { @@ -135,7 +134,7 @@ public class ReplicatedRegionFactoryBeanTest { factoryBean.resolveDataPolicy(mockRegionFactory, null, "PARTITION"); } catch (IllegalArgumentException e) { - assertEquals("Data Policy 'PARTITION' is not supported in Replicated Regions.", e.getMessage()); + assertEquals("Data Policy [PARTITION] is not supported in Replicated Regions.", e.getMessage()); throw e; } finally { diff --git a/src/test/java/org/springframework/data/gemfire/util/RegionUtilsUnitTests.java b/src/test/java/org/springframework/data/gemfire/util/RegionUtilsUnitTests.java index f94437c3..30ad8dab 100644 --- a/src/test/java/org/springframework/data/gemfire/util/RegionUtilsUnitTests.java +++ b/src/test/java/org/springframework/data/gemfire/util/RegionUtilsUnitTests.java @@ -17,9 +17,17 @@ package org.springframework.data.gemfire.util; import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.doThrow; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import org.junit.Test; import org.apache.geode.cache.DataPolicy; -import org.junit.Test; +import org.apache.geode.cache.Region; +import org.apache.geode.cache.RegionService; /** * Unit tests for {@link RegionUtils}. @@ -34,9 +42,9 @@ public class RegionUtilsUnitTests { public void assertAllDataPoliciesWithNullPersistentPropertyIsCompatible() { RegionUtils.assertDataPolicyAndPersistentAttributeAreCompatible(DataPolicy.PARTITION, null); - RegionUtils.assertDataPolicyAndPersistentAttributeAreCompatible(DataPolicy.REPLICATE, null); RegionUtils.assertDataPolicyAndPersistentAttributeAreCompatible(DataPolicy.PERSISTENT_PARTITION, null); RegionUtils.assertDataPolicyAndPersistentAttributeAreCompatible(DataPolicy.PERSISTENT_REPLICATE, null); + RegionUtils.assertDataPolicyAndPersistentAttributeAreCompatible(DataPolicy.REPLICATE, null); } @Test @@ -54,7 +62,7 @@ public class RegionUtilsUnitTests { } @Test(expected = IllegalArgumentException.class) - public void testAssertNonPersistentDataPolicyWithPersistentAttribute() { + public void assertNonPersistentDataPolicyWithPersistentAttribute() { try { RegionUtils.assertDataPolicyAndPersistentAttributeAreCompatible(DataPolicy.REPLICATE, true); @@ -69,7 +77,7 @@ public class RegionUtilsUnitTests { } @Test(expected = IllegalArgumentException.class) - public void testAssertPersistentDataPolicyWithNonPersistentAttribute() { + public void assertPersistentDataPolicyWithNonPersistentAttribute() { try { RegionUtils.assertDataPolicyAndPersistentAttributeAreCompatible(DataPolicy.PERSISTENT_PARTITION, false); @@ -82,4 +90,78 @@ public class RegionUtilsUnitTests { throw expected; } } + + @Test + public void closeRegionHandlesNull() { + assertThat(RegionUtils.close((Region) null)).isFalse(); + } + + @Test + public void closeRegionSuccessfully() { + + Region mockRegion = mock(Region.class); + + assertThat(RegionUtils.close(mockRegion)).isTrue(); + + verify(mockRegion, times(1)).close(); + } + + @Test + public void closeRegionUnsuccessfully() { + + Region mockRegion = mock(Region.class); + + doThrow(new RuntimeException("TEST")).when(mockRegion).close(); + + assertThat(RegionUtils.close(mockRegion)).isFalse(); + + verify(mockRegion, times(1)).close(); + } + + @Test + public void nullRegionIsNotCloseable() { + assertThat(RegionUtils.isCloseable(null)).isFalse(); + } + + @Test + public void regionIsCloseable() { + + Region mockRegion = mock(Region.class); + RegionService mockRegionService = mock(RegionService.class); + + when(mockRegion.getRegionService()).thenReturn(mockRegionService); + when(mockRegionService.isClosed()).thenReturn(false); + + assertThat(RegionUtils.isCloseable(mockRegion)).isTrue(); + + verify(mockRegion, times(1)).getRegionService(); + verify(mockRegionService, times(1)).isClosed(); + } + + @Test + public void regionIsNotCloseable() { + + Region mockRegion = mock(Region.class); + RegionService mockRegionService = mock(RegionService.class); + + when(mockRegion.getRegionService()).thenReturn(mockRegionService); + when(mockRegionService.isClosed()).thenReturn(true); + + assertThat(RegionUtils.isCloseable(mockRegion)).isFalse(); + + verify(mockRegion, times(1)).getRegionService(); + verify(mockRegionService, times(1)).isClosed(); + } + + @Test + public void regionWithNoRegionServiceIsNotCloseable() { + + Region mockRegion = mock(Region.class); + + when(mockRegion.getRegionService()).thenReturn(null); + + assertThat(RegionUtils.isCloseable(mockRegion)).isFalse(); + + verify(mockRegion, times(1)).getRegionService(); + } }