diff --git a/src/test/java/org/springframework/data/gemfire/config/RegionWithSubRegionBeanDefinitionHashCodeTest.java b/src/test/java/org/springframework/data/gemfire/config/RegionWithSubRegionBeanDefinitionHashCodeTest.java new file mode 100644 index 00000000..1cc9df84 --- /dev/null +++ b/src/test/java/org/springframework/data/gemfire/config/RegionWithSubRegionBeanDefinitionHashCodeTest.java @@ -0,0 +1,117 @@ +/* + * Copyright 2010-2013 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.data.gemfire.config; + +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.config.BeanDefinition; +import org.springframework.context.support.AbstractApplicationContext; +import org.springframework.data.gemfire.test.GemfireTestApplicationContextInitializer; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +/** + * The RegionWithSubRegionBeanDefinitionHashCodeTest class is a test suite for testing the hashCode() method of a + * Spring container BeanDefinition representing a GemFire Region having SubRegions. This test suite is meant to + * ensure the correct behavior of and provide regression coverage for, JIRA issue SGF-178, "parent attribute causes + * endless loop in hashCode". + *
+ * The 'parent' attribute was added to the parent Region's BeanDefinition, referring to the parent Region's + * BeanDefinition itself, before it recurses to parse the SubRegion elements, which is then used by the + * AbstractRegionParser.doParseInternal method to set the parent property of the SubRegion's BeanDefinition. + * + * Calling hashCode on a parent Region's BeanDefinition that has a parent 'attribute' referring to the parent Region's + * BeanDefinition itself, causes infinite recursion and an eventual StackOverflowError. + * + *
+ * java.lang.StackOverflowError
+ * at java.util.LinkedHashMap$LinkedHashIterator.(LinkedHashMap.java:345)
+ * at java.util.LinkedHashMap$LinkedHashIterator.(LinkedHashMap.java:345)
+ * at java.util.LinkedHashMap$EntryIterator.(LinkedHashMap.java:391)
+ * at java.util.LinkedHashMap$EntryIterator.(LinkedHashMap.java:391)
+ * at java.util.LinkedHashMap.newEntryIterator(LinkedHashMap.java:398)
+ * at java.util.HashMap$EntrySet.iterator(HashMap.java:950)
+ * at org.springframework.beans.factory.config.ConstructorArgumentValues.hashCode(ConstructorArgumentValues.java:416)
+ * at org.springframework.util.ObjectUtils.nullSafeHashCode(ObjectUtils.java:336)
+ * at org.springframework.beans.factory.support.AbstractBeanDefinition.hashCode(AbstractBeanDefinition.java:1048)
+ * at org.springframework.beans.factory.config.BeanDefinitionHolder.hashCode(BeanDefinitionHolder.java:179)
+ * at org.springframework.util.ObjectUtils.nullSafeHashCode(ObjectUtils.java:336)
+ * at org.springframework.beans.BeanMetadataAttribute.hashCode(BeanMetadataAttribute.java:93)
+ * at java.util.HashMap$Entry.hashCode(HashMap.java:720)
+ * at java.util.AbstractMap.hashCode(AbstractMap.java:461)
+ * at org.springframework.core.AttributeAccessorSupport.hashCode(AttributeAccessorSupport.java:99)
+ * at org.springframework.beans.factory.support.AbstractBeanDefinition.hashCode(AbstractBeanDefinition.java:1052)
+ * at org.springframework.beans.factory.config.BeanDefinitionHolder.hashCode(BeanDefinitionHolder.java:179)
+ * at org.springframework.util.ObjectUtils.nullSafeHashCode(ObjectUtils.java:336)
+ * at org.springframework.beans.BeanMetadataAttribute.hashCode(BeanMetadataAttribute.java:93)
+ * at java.util.HashMap$Entry.hashCode(HashMap.java:720)
+ * at java.util.AbstractMap.hashCode(AbstractMap.java:461)
+ * ...
+ * at org.springframework.core.AttributeAccessorSupport.hashCode(AttributeAccessorSupport.java:99)
+ * at org.springframework.beans.factory.support.AbstractBeanDefinition.hashCode(AbstractBeanDefinition.java:1052)
+ *
+ *
+ * This also causes problems for tools like Spring Tool Suite, which use the BeanDefinitions from the Spring container
+ * context as meta-data in the IDE.
+ *
+ * @author John Blum
+ * @see org.junit.Test
+ * @see org.junit.runner.RunWith
+ * @see org.springframework.data.gemfire.test.GemfireTestApplicationContextInitializer
+ * @see org.springframework.test.context.ContextConfiguration
+ * @see org.springframework.test.context.junit4.SpringJUnit4ClassRunner
+ * @link https://jira.springsource.org/browse/SGF-178
+ * @since 1.3.3
+ */
+@ContextConfiguration(locations="/org/springframework/data/gemfire/config/RegionWithSubRegionBeanDefinitionHashCodeTest-context.xml",
+ initializers=GemfireTestApplicationContextInitializer.class)
+@RunWith(SpringJUnit4ClassRunner.class)
+@SuppressWarnings("unused")
+public class RegionWithSubRegionBeanDefinitionHashCodeTest {
+
+ @Autowired
+ private AbstractApplicationContext context;
+
+ @Test
+ public void testNonParentRegionBeanDefinitionHashCode() {
+ final BeanDefinition nonParentRegionBeanDefinition = context.getBeanFactory().getBeanDefinition("NON_PARENT");
+
+ assertNotNull(nonParentRegionBeanDefinition);
+ assertTrue(nonParentRegionBeanDefinition.hashCode() != 0);
+ }
+
+ @Test
+ public void testParentRegionBeanDefinitionHashCode() {
+ final BeanDefinition parentRegionBeanDefinition = context.getBeanFactory().getBeanDefinition("PARENT");
+
+ assertNotNull(parentRegionBeanDefinition);
+ assertTrue(parentRegionBeanDefinition.hashCode() != 0);
+ }
+
+ @Test
+ public void testChildRegionBeanDefinitionHashCode() {
+ final BeanDefinition childRegionBeanDefinition = context.getBeanFactory().getBeanDefinition("/PARENT/CHILD");
+
+ assertNotNull(childRegionBeanDefinition);
+ assertTrue(childRegionBeanDefinition.hashCode() != 0);
+ }
+
+}
diff --git a/src/test/resources/org/springframework/data/gemfire/config/RegionWithSubRegionBeanDefinitionHashCodeTest-context.xml b/src/test/resources/org/springframework/data/gemfire/config/RegionWithSubRegionBeanDefinitionHashCodeTest-context.xml
new file mode 100644
index 00000000..53164758
--- /dev/null
+++ b/src/test/resources/org/springframework/data/gemfire/config/RegionWithSubRegionBeanDefinitionHashCodeTest-context.xml
@@ -0,0 +1,23 @@
+
+