From cd79555066390525f70e9e49d5ed266e95d01a77 Mon Sep 17 00:00:00 2001 From: Udo Kohlmeyer Date: Tue, 12 May 2020 12:15:05 -0700 Subject: [PATCH] DATAGEODE-337 - LookupRegionMutationIntegrationTest fails due to parallel AEQ on REPLICATE Region. Adapts to API changes in Apache Geode 1.14, specifically fixing broken tests (i.e LookupRegionMutationIntegrationTests) which configured a REPLICATE Region with a "parallel" AEQ that is no longer supported in 1.14 forward. See GEODE-8079 (https://issues.apache.org/jira/browse/GEODE-8079). Resolves gh-41. Resolves gh-389. --- ...artitionRegionMutationIntegrationTest.java | 287 ++++++++++++++++++ ...lookup-partition-region-mutation-cache.xml | 16 + ...nRegionMutationIntegrationTest-context.xml | 53 ++++ ...pRegionMutationIntegrationTest-context.xml | 2 +- 4 files changed, 357 insertions(+), 1 deletion(-) create mode 100644 spring-data-geode/src/test/java/org/springframework/data/gemfire/LookupPartitionRegionMutationIntegrationTest.java create mode 100644 spring-data-geode/src/test/resources/lookup-partition-region-mutation-cache.xml create mode 100644 spring-data-geode/src/test/resources/org/springframework/data/gemfire/LookupPartitionRegionMutationIntegrationTest-context.xml diff --git a/spring-data-geode/src/test/java/org/springframework/data/gemfire/LookupPartitionRegionMutationIntegrationTest.java b/spring-data-geode/src/test/java/org/springframework/data/gemfire/LookupPartitionRegionMutationIntegrationTest.java new file mode 100644 index 00000000..c6bc243b --- /dev/null +++ b/spring-data-geode/src/test/java/org/springframework/data/gemfire/LookupPartitionRegionMutationIntegrationTest.java @@ -0,0 +1,287 @@ +/* + * Copyright 2010-2020 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.data.gemfire; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.List; + +import javax.annotation.Resource; + +import org.apache.geode.cache.CacheListener; +import org.apache.geode.cache.CacheLoader; +import org.apache.geode.cache.CacheLoaderException; +import org.apache.geode.cache.CacheWriter; +import org.apache.geode.cache.CacheWriterException; +import org.apache.geode.cache.CustomExpiry; +import org.apache.geode.cache.DataPolicy; +import org.apache.geode.cache.EntryEvent; +import org.apache.geode.cache.EvictionAction; +import org.apache.geode.cache.EvictionAlgorithm; +import org.apache.geode.cache.EvictionAttributes; +import org.apache.geode.cache.ExpirationAction; +import org.apache.geode.cache.ExpirationAttributes; +import org.apache.geode.cache.LoaderHelper; +import org.apache.geode.cache.Region; +import org.apache.geode.cache.RegionEvent; +import org.apache.geode.cache.asyncqueue.AsyncEvent; +import org.apache.geode.cache.asyncqueue.AsyncEventListener; +import org.apache.geode.cache.util.CacheListenerAdapter; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.BeanNameAware; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringRunner; +import org.springframework.util.StringUtils; + +/** + * The LookupRegionMutationIntegrationTest class is a test suite of test cases testing the contract and integrated + * functionality between natively-defined GemFire Cache Regions and SDG's Region lookup functionality combined with + * Region attribute(s) mutation. + * + * @author John Blum + * @see Test + * @see RunWith + * @see LookupRegionFactoryBean + * @see ContextConfiguration + * @see org.springframework.test.context.junit4.SpringJUnit4ClassRunner + * @since 1.7.0 + */ +@RunWith(SpringRunner.class) +@ContextConfiguration +@SuppressWarnings("unused") +public class LookupPartitionRegionMutationIntegrationTest { + + @Resource(name = "Example") + private Region example; + + private void assertCacheListeners(CacheListener[] cacheListeners, Collection expectedCacheListenerNames) { + + if (!expectedCacheListenerNames.isEmpty()) { + assertNotNull("CacheListeners must not be null!", cacheListeners); + assertEquals(expectedCacheListenerNames.size(), cacheListeners.length); + assertTrue(toStrings(cacheListeners).containsAll(expectedCacheListenerNames)); + } + } + + private void assertEvictionAttributes(EvictionAttributes evictionAttributes, EvictionAction expectedAction, + EvictionAlgorithm expectedAlgorithm, int expectedMaximum) { + + assertNotNull("EvictionAttributes must not be null!", evictionAttributes); + assertEquals(expectedAction, evictionAttributes.getAction()); + assertEquals(expectedAlgorithm, evictionAttributes.getAlgorithm()); + assertEquals(expectedMaximum, evictionAttributes.getMaximum()); + } + + private void assertExpirationAttributes(ExpirationAttributes expirationAttributes, + + String description, int expectedTimeout, ExpirationAction expectedAction) { + + assertNotNull(String.format("ExpirationAttributes for '%1$s' must not be null!", description), + expirationAttributes); + assertEquals(expectedAction, expirationAttributes.getAction()); + assertEquals(expectedTimeout, expirationAttributes.getTimeout()); + } + + private void assertGatewaySenders(Region region, List expectedGatewaySenderIds) { + + assertNotNull(region.getAttributes()); + assertNotNull(region.getAttributes().getGatewaySenderIds()); + assertEquals(expectedGatewaySenderIds.size(), region.getAttributes().getGatewaySenderIds().size()); + assertTrue(expectedGatewaySenderIds.containsAll(region.getAttributes().getGatewaySenderIds())); + } + + private void assertGemFireComponent(Object gemfireComponent, String expectedName) { + + assertNotNull("The GemFire component must not be null!", gemfireComponent); + assertEquals(expectedName, gemfireComponent.toString()); + } + + private void assertRegionAttributes(Region region, String expectedName, DataPolicy expectedDataPolicy) { + + assertRegionAttributes(region, expectedName, String.format("%1$s%2$s", Region.SEPARATOR, expectedName), + expectedDataPolicy); + } + + private void assertRegionAttributes(Region region, String expectedName, String expectedFullPath, + DataPolicy expectedDataPolicy) { + + assertNotNull(String.format("'%1$s' Region was not properly initialized!", region)); + assertEquals(expectedName, region.getName()); + assertEquals(expectedFullPath, region.getFullPath()); + assertNotNull(region.getAttributes()); + assertEquals(expectedDataPolicy, region.getAttributes().getDataPolicy()); + } + + private Collection toStrings(Object[] objects) { + + List cacheListenerNames = new ArrayList<>(objects.length); + + for (Object object : objects) { + cacheListenerNames.add(object.toString()); + } + + return cacheListenerNames; + } + + /** + * @see EvictionAttributesMutator.setMaximum does not work + */ + @Test + public void regionConfigurationIsCorrect() { + + assertRegionAttributes(example, "Example", DataPolicy.PARTITION); + assertEquals(13, example.getAttributes().getInitialCapacity()); + assertEquals(0.85f, example.getAttributes().getLoadFactor(), 0.0f); + assertCacheListeners(example.getAttributes().getCacheListeners(), Arrays.asList("A", "B")); + assertGemFireComponent(example.getAttributes().getCacheLoader(), "C"); + assertGemFireComponent(example.getAttributes().getCacheWriter(), "D"); + assertEvictionAttributes(example.getAttributes().getEvictionAttributes(), EvictionAction.OVERFLOW_TO_DISK, + EvictionAlgorithm.LRU_ENTRY, 1000); + assertGemFireComponent(example.getAttributes().getCustomEntryIdleTimeout(), "E"); + assertNotNull(example.getAttributes().getAsyncEventQueueIds()); + assertEquals(1, example.getAttributes().getAsyncEventQueueIds().size()); + assertEquals("AEQ", example.getAttributes().getAsyncEventQueueIds().iterator().next()); + assertGatewaySenders(example, Collections.singletonList("GWS")); + } + + interface Nameable extends BeanNameAware { + + String getName(); + + void setName(String name); + } + + static abstract class AbstractNameable implements Nameable { + + private String name; + + public String getName() { + return name; + } + + public void setName(final String name) { + this.name = name; + } + + @Override + public void setBeanName(final String name) { + if (!StringUtils.hasText(this.name)) { + setName(name); + } + } + + @Override + public String toString() { + return getName(); + } + } + + public static final class TestAsyncEventListener extends AbstractNameable implements AsyncEventListener { + + @Override + public boolean processEvents(List events) { + throw new UnsupportedOperationException("Not Implemented!"); + } + + @Override + public void close() { + } + } + + public static final class TestCacheListener extends CacheListenerAdapter implements Nameable { + + private String name; + + public String getName() { + return name; + } + + public void setName(final String name) { + this.name = name; + } + + @Override + public void setBeanName(final String name) { + if (!StringUtils.hasText(this.name)) { + setName(name); + } + } + + @Override + public String toString() { + return getName(); + } + } + + public static final class TestCacheLoader extends AbstractNameable implements CacheLoader { + + @Override + public V load(LoaderHelper helper) throws CacheLoaderException { + throw new UnsupportedOperationException("Not Implemented!"); + } + + @Override + public void close() { + } + } + + public static final class TestCacheWriter extends AbstractNameable implements CacheWriter { + + @Override + public void beforeUpdate(EntryEvent event) throws CacheWriterException { + } + + @Override + public void beforeCreate(EntryEvent event) throws CacheWriterException { + } + + @Override + public void beforeDestroy(EntryEvent event) throws CacheWriterException { + } + + @Override + public void beforeRegionDestroy(RegionEvent event) throws CacheWriterException { + } + + @Override + public void beforeRegionClear(RegionEvent event) throws CacheWriterException { + } + + @Override + public void close() { + } + } + + public static final class TestCustomExpiry extends AbstractNameable implements CustomExpiry { + + @Override + public ExpirationAttributes getExpiry(Region.Entry entry) { + throw new UnsupportedOperationException("Not Implemented!"); + } + + @Override + public void close() { + } + } +} diff --git a/spring-data-geode/src/test/resources/lookup-partition-region-mutation-cache.xml b/spring-data-geode/src/test/resources/lookup-partition-region-mutation-cache.xml new file mode 100644 index 00000000..97dac13a --- /dev/null +++ b/spring-data-geode/src/test/resources/lookup-partition-region-mutation-cache.xml @@ -0,0 +1,16 @@ + + + + + + + + + + + + diff --git a/spring-data-geode/src/test/resources/org/springframework/data/gemfire/LookupPartitionRegionMutationIntegrationTest-context.xml b/spring-data-geode/src/test/resources/org/springframework/data/gemfire/LookupPartitionRegionMutationIntegrationTest-context.xml new file mode 100644 index 00000000..62babfb5 --- /dev/null +++ b/spring-data-geode/src/test/resources/org/springframework/data/gemfire/LookupPartitionRegionMutationIntegrationTest-context.xml @@ -0,0 +1,53 @@ + + + + + LookupRegionMutationIntegrationTest + error + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/spring-data-geode/src/test/resources/org/springframework/data/gemfire/LookupRegionMutationIntegrationTest-context.xml b/spring-data-geode/src/test/resources/org/springframework/data/gemfire/LookupRegionMutationIntegrationTest-context.xml index ae9640ee..cfaf817d 100644 --- a/spring-data-geode/src/test/resources/org/springframework/data/gemfire/LookupRegionMutationIntegrationTest-context.xml +++ b/spring-data-geode/src/test/resources/org/springframework/data/gemfire/LookupRegionMutationIntegrationTest-context.xml @@ -41,7 +41,7 @@ p:name="E"/> - +