SGF-434 - Add a durable GemFire client cache test to assert proper behavior by SDG.

This commit is contained in:
John Blum
2015-10-03 18:34:30 -07:00
parent 2344eb521d
commit b52a18579b
22 changed files with 1032 additions and 101 deletions

View File

@@ -78,7 +78,7 @@ import com.gemstone.gemfire.pdx.PdxSerializer;
* @see org.springframework.dao.support.PersistenceExceptionTranslator
*/
@SuppressWarnings("unused")
public class CacheFactoryBean implements BeanClassLoaderAware, BeanFactoryAware, BeanNameAware, FactoryBean<Cache>,
public class CacheFactoryBean implements BeanClassLoaderAware, BeanFactoryAware, BeanNameAware, FactoryBean<GemFireCache>,
InitializingBean, DisposableBean, PersistenceExceptionTranslator {
protected boolean close = true;
@@ -96,7 +96,7 @@ public class CacheFactoryBean implements BeanClassLoaderAware, BeanFactoryAware,
protected Boolean pdxReadSerialized;
protected Boolean useClusterConfiguration;
protected Cache cache;
protected GemFireCache cache;
protected ClassLoader beanClassLoader;
@@ -226,7 +226,7 @@ public class CacheFactoryBean implements BeanClassLoaderAware, BeanFactoryAware,
}
/* (non-Javadoc) */
private Cache init() throws Exception {
private GemFireCache init() throws Exception {
initBeanFactoryLocator();
final ClassLoader currentThreadContextClassLoader = Thread.currentThread().getContextClassLoader();
@@ -497,7 +497,7 @@ public class CacheFactoryBean implements BeanClassLoaderAware, BeanFactoryAware,
Cache localCache = fetchCache();
if (localCache != null && !localCache.isClosed()) {
localCache.close();
close(localCache);
}
this.cache = null;
@@ -509,6 +509,10 @@ public class CacheFactoryBean implements BeanClassLoaderAware, BeanFactoryAware,
}
}
protected void close(GemFireCache cache) {
cache.close();
}
@Override
public DataAccessException translateExceptionIfPossible(RuntimeException e) {
if (e instanceof GemFireException) {
@@ -844,7 +848,7 @@ public class CacheFactoryBean implements BeanClassLoaderAware, BeanFactoryAware,
}
@Override
public Cache getObject() throws Exception {
public GemFireCache getObject() throws Exception {
return init();
}

View File

@@ -23,6 +23,7 @@ import org.springframework.util.ClassUtils;
import com.gemstone.gemfire.cache.CacheFactory;
import com.gemstone.gemfire.cache.Region;
import com.gemstone.gemfire.cache.client.ClientCacheFactory;
/**
* GemfireUtils is an abstract utility class encapsulating common functionality to access features and capabilities
@@ -32,10 +33,31 @@ import com.gemstone.gemfire.cache.Region;
* @see org.springframework.data.gemfire.util.DistributedSystemUtils
* @since 1.3.3
*/
@SuppressWarnings("unused")
public abstract class GemfireUtils extends DistributedSystemUtils {
public final static String GEMFIRE_VERSION = CacheFactory.getVersion();
public static boolean closeCache() {
try {
CacheFactory.getAnyInstance().close();
return true;
}
catch (Exception ignore) {
return false;
}
}
public static boolean closeClientCache() {
try {
ClientCacheFactory.getAnyInstance().close();
return true;
}
catch (Exception ignore) {
return false;
}
}
public static boolean isGemfireVersionGreaterThanEqual(double expectedVersion) {
double actualVersion = Double.parseDouble(GEMFIRE_VERSION.substring(0, 3));
return actualVersion >= expectedVersion;

View File

@@ -16,10 +16,11 @@
package org.springframework.data.gemfire.client;
import java.io.IOException;
import java.util.Properties;
import org.springframework.beans.factory.BeanInitializationException;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.data.gemfire.CacheFactoryBean;
import org.springframework.data.gemfire.GemfireUtils;
import org.springframework.data.gemfire.config.GemfireConstants;
@@ -40,19 +41,26 @@ import com.gemstone.gemfire.pdx.PdxSerializer;
* @author Costin Leau
* @author Lyndon Adams
* @author John Blum
* @see org.springframework.context.ApplicationListener
* @see org.springframework.context.event.ContextRefreshedEvent
* @see org.springframework.data.gemfire.CacheFactoryBean
* @see com.gemstone.gemfire.cache.GemFireCache
* @see com.gemstone.gemfire.cache.client.ClientCache
* @see com.gemstone.gemfire.cache.client.ClientCacheFactory
* @see com.gemstone.gemfire.cache.client.Pool
* @see com.gemstone.gemfire.cache.client.PoolManager
* @see com.gemstone.gemfire.distributed.DistributedSystem
*/
@SuppressWarnings("unused")
public class ClientCacheFactoryBean extends CacheFactoryBean {
public class ClientCacheFactoryBean extends CacheFactoryBean implements ApplicationListener<ContextRefreshedEvent> {
protected Boolean keepAlive = false;
protected Boolean readyForEvents = false;
private Pool pool;
private String poolName;
protected String poolName;
@Override
protected void postProcessPropertiesBeforeInitialization(Properties gemfireProperties) {
@@ -213,18 +221,14 @@ public class ClientCacheFactoryBean extends CacheFactoryBean {
/**
* Register for events after Pool and Regions have been created and iff non-durable client...
*
* @param <T> parameterized Class type extension of GemFireCache.
* @param cache the GemFire cache instance to process.
* @return the processed cache instance after ready for events.
* @throws java.io.IOException if an error occurs during post processing.
* @see org.springframework.data.gemfire.CacheFactoryBean#postProcess(com.gemstone.gemfire.cache.GemFireCache)
* @see #readyForEvents(com.gemstone.gemfire.cache.GemFireCache)
* @see com.gemstone.gemfire.cache.GemFireCache
* @param event the ApplicationContextEvent fired when the ApplicationContext is refreshed.
* @see org.springframework.context.Lifecycle#start()
* @see com.gemstone.gemfire.cache.client.ClientCache
* @see #readyForEvents(com.gemstone.gemfire.cache.GemFireCache)
*/
@Override
protected <T extends GemFireCache> T postProcess(T cache) throws IOException {
return readyForEvents(super.postProcess(cache));
public void onApplicationEvent(final ContextRefreshedEvent event) {
readyForEvents(this.cache);
}
/**
@@ -243,6 +247,11 @@ public class ClientCacheFactoryBean extends CacheFactoryBean {
return clientCache;
}
@Override
protected void close(final GemFireCache cache) {
((ClientCache) cache).close(isKeepAlive());
}
@Override
public final void setEnableAutoReconnect(final Boolean enableAutoReconnect) {
throw new UnsupportedOperationException("Auto-reconnect is not supported on ClientCache.");
@@ -258,6 +267,26 @@ public class ClientCacheFactoryBean extends CacheFactoryBean {
return (cache != null ? cache.getClass() : ClientCache.class);
}
/**
* Sets whether the server(s) should keep the durable client's queue alive for the duration of the timeout
* when the client voluntarily disconnects.
*
* @param keepAlive a boolean value indicating to the server to keep the durable client's queues alive.
*/
public void setKeepAlive(Boolean keepAlive) {
this.keepAlive = keepAlive;
}
/**
* Determines whether the server(s) should keep the durable client's queue alive for the duration of the timeout
* when the client voluntarily disconnects.
*
* @return a boolean value indicating whether the server should keep the durable client's queues alive.
*/
public boolean isKeepAlive() {
return Boolean.TRUE.equals(this.keepAlive);
}
/**
* Sets the pool used by this client.
*
@@ -278,6 +307,15 @@ public class ClientCacheFactoryBean extends CacheFactoryBean {
this.poolName = poolName;
}
/**
* Gets the pool name used by this client.
*
* @return the name of the GemFire Pool used by the GemFire Client Cache.
*/
public String getPoolName() {
return poolName;
}
/**
* Set the readyForEvents flag.
*

View File

@@ -49,6 +49,14 @@ import com.gemstone.gemfire.internal.cache.GemFireCacheImpl;
* @author Costin Leau
* @author David Turanski
* @author John Blum
* @see org.springframework.beans.factory.BeanFactory
* @see org.springframework.beans.factory.BeanFactoryAware
* @see org.springframework.beans.factory.DisposableBean
* @see org.springframework.data.gemfire.RegionLookupFactoryBean
* @see com.gemstone.gemfire.cache.GemFireCache
* @see com.gemstone.gemfire.cache.client.ClientCache
* @see com.gemstone.gemfire.cache.client.ClientRegionFactory
* @see com.gemstone.gemfire.cache.client.ClientRegionShortcut
*/
@SuppressWarnings("unused")
public class ClientRegionFactoryBean<K, V> extends RegionLookupFactoryBean<K, V> implements BeanFactoryAware,
@@ -89,7 +97,7 @@ public class ClientRegionFactoryBean<K, V> extends RegionLookupFactoryBean<K, V>
}
@Override
@SuppressWarnings("deprecation")
@SuppressWarnings("all")
protected Region<K, V> lookupFallback(GemFireCache cache, String regionName) throws Exception {
Assert.isTrue(cache instanceof ClientCache, String.format("Unable to create Regions from %1$s!", cache));
@@ -298,24 +306,6 @@ public class ClientRegionFactoryBean<K, V> extends RegionLookupFactoryBean<K, V>
public void destroy() throws Exception {
Region<K, V> region = getObject();
try {
if (region != null && !ObjectUtils.isEmpty(interests)) {
for (Interest<K> interest : interests) {
if (interest instanceof RegexInterest) {
region.unregisterInterestRegex((String) interest.getKey());
}
else {
region.unregisterInterest(interest.getKey());
}
}
}
}
// NOTE AdminRegion, LocalDataSet, Proxy Region and RegionCreation all throw UnsupportedOperationException;
// however, should not really happen since Interests are validated at start/registration
catch (UnsupportedOperationException ex) {
log.warn("Cannot unregister cache interests", ex);
}
if (region != null) {
if (close) {
if (!region.getRegionService().isClosed()) {
@@ -326,8 +316,8 @@ public class ClientRegionFactoryBean<K, V> extends RegionLookupFactoryBean<K, V>
}
}
}
// TODO I think Region.close and Region.destroyRegion are mutually exclusive; thus, 1 operation (e.g. close)
// does not cancel the other (i.e. destroy). This should just be if, not else if.
// TODO perhaps 'destroy' should take precedence over 'close' since 'destroy' is a functional superset
// of 'close'
else if (destroy) {
region.destroyRegion();
}

View File

@@ -243,18 +243,10 @@ public class PoolFactoryBean implements FactoryBean<Pool>, InitializingBean, Dis
this.beanName = name;
}
/**
* @param name
* the name to set
*/
public void setName(String name) {
this.name = name;
}
/**
* @param pool
* the pool to set
*/
public void setPool(Pool pool) {
this.pool = pool;
}

View File

@@ -38,6 +38,7 @@ class ClientCacheParser extends CacheParser {
@Override
protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) {
super.doParse(element, parserContext, builder);
ParsingUtils.setPropertyValue(element, builder, "keep-alive", "keepAlive");
ParsingUtils.setPropertyValue(element, builder, "pool-name", "poolName");
ParsingUtils.setPropertyValue(element, builder, "ready-for-events");
}

View File

@@ -349,6 +349,12 @@ Defines a GemFire Client Cache instance used for creating or retrieving 'regions
<xsd:complexType>
<xsd:complexContent>
<xsd:extension base="cacheBaseType">
<xsd:attribute name="keep-alive" type="xsd:string" use="optional" default="false">
<xsd:annotation>
<xsd:documentation><![CDATA[
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="pool-name" type="xsd:string" use="optional">
<xsd:annotation>
<xsd:documentation><![CDATA[

View File

@@ -16,11 +16,13 @@
package org.springframework.data.gemfire;
import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import static org.junit.Assume.assumeTrue;
import static org.mockito.Matchers.any;
@@ -417,6 +419,7 @@ public class CacheFactoryBeanTest {
}
@Test
@SuppressWarnings("unchecked")
public void getObject() throws Exception {
final ClassLoader expectedThreadContextClassLoader = Thread.currentThread().getContextClassLoader();
final Cache mockCache = mock(Cache.class, "GemFireCache");
@@ -443,24 +446,25 @@ public class CacheFactoryBeanTest {
cacheFactoryBean.setBeanClassLoader(ClassLoader.getSystemClassLoader());
cacheFactoryBean.setBeanName("MockGemFireCache");
cacheFactoryBean.setCopyOnRead(true);
cacheFactoryBean.setLockLease(15000);
cacheFactoryBean.setLockTimeout(5000);
cacheFactoryBean.setSearchTimeout(15000);
cacheFactoryBean.setUseBeanFactoryLocator(false);
Cache actualCache = cacheFactoryBean.getObject();
GemFireCache actualCache = cacheFactoryBean.getObject();
assertSame(mockCache, actualCache);
assertSame(expectedThreadContextClassLoader, Thread.currentThread().getContextClassLoader());
verify(mockCache, times(1)).setCopyOnRead(eq(true));
verify(mockCache, times(1)).setLockTimeout(eq(5000));
verify(mockCache, times(1)).setSearchTimeout(eq(15000));
verify(mockCache, never()).getCacheTransactionManager();
verify(mockCache, never()).getResourceManager();
verify(mockCache, never()).loadCacheXml(any(InputStream.class));
verify(mockCache, times(1)).setCopyOnRead(eq(true));
verify(mockCache, never()).setGatewayConflictResolver(any(GatewayConflictResolver.class));
verify(mockCache, never()).setLockLease(anyInt());
verify(mockCache, times(1)).setLockLease(eq(15000));
verify(mockCache, times(1)).setLockTimeout(eq(5000));
verify(mockCache, never()).setMessageSyncInterval(anyInt());
verify(mockCache, times(1)).setSearchTimeout(eq(15000));
verify(mockCache, never()).getResourceManager();
verify(mockCache, never()).getCacheTransactionManager();
}
@Test
@@ -474,7 +478,9 @@ public class CacheFactoryBeanTest {
}
@Test
@SuppressWarnings("unchecked")
public void destroy() throws Exception {
final AtomicBoolean fetchCacheCalled = new AtomicBoolean(false);
final Cache mockCache = mock(Cache.class, "GemFireCache");
GemfireBeanFactoryLocator mockGemfireBeanFactoryLocator = mock(GemfireBeanFactoryLocator.class);
@@ -483,6 +489,7 @@ public class CacheFactoryBeanTest {
CacheFactoryBean cacheFactoryBean = new CacheFactoryBean() {
@Override protected GemFireCache fetchCache() {
fetchCacheCalled.set(true);
return mockCache;
}
};
@@ -494,12 +501,15 @@ public class CacheFactoryBeanTest {
cacheFactoryBean.setUseBeanFactoryLocator(true);
cacheFactoryBean.destroy();
assertThat(fetchCacheCalled.get(), is(true));
verify(mockCache, times(1)).isClosed();
verify(mockCache, times(1)).close();
verify(mockGemfireBeanFactoryLocator, times(1)).destroy();
}
@Test
@SuppressWarnings("unchecked")
public void destroyWhenCacheIsNull() throws Exception {
final AtomicBoolean fetchCacheCalled = new AtomicBoolean(false);
@@ -518,7 +528,8 @@ public class CacheFactoryBeanTest {
}
@Test
public void destroyWhenClosedIsFalse() throws Exception {
@SuppressWarnings("unchecked")
public void destroyWhenCacheClosedIsTrue() throws Exception {
final AtomicBoolean fetchCacheCalled = new AtomicBoolean(false);
final Cache mockCache = mock(Cache.class, "GemFireCache");
@@ -539,6 +550,15 @@ public class CacheFactoryBeanTest {
assertFalse(fetchCacheCalled.get());
}
@Test
public void closeCache() {
GemFireCache mockCache = mock(GemFireCache.class, "testCloseCache.MockCache");
new CacheFactoryBean().close(mockCache);
verify(mockCache, times(1)).close();
}
@Test
public void setAndGetCacheFactoryBeanProperties() throws Exception {
BeanFactory mockBeanFactory = mock(BeanFactory.class, "SpringBeanFactory");

View File

@@ -18,8 +18,6 @@ package org.springframework.data.gemfire;
import static org.junit.Assert.assertEquals;
import junit.framework.Assert;
import org.junit.After;
import org.junit.Test;
import org.junit.runner.RunWith;

View File

@@ -21,7 +21,7 @@ import static org.junit.Assert.assertSame;
import org.junit.Test;
import com.gemstone.gemfire.cache.Cache;
import com.gemstone.gemfire.cache.GemFireCache;
import com.gemstone.gemfire.cache.Region;
/**
@@ -49,7 +49,7 @@ public class SubRegionTest extends RecreatingContextTest {
cacheFactoryBean.setBeanName("gemfireCache");
cacheFactoryBean.setUseBeanFactoryLocator(false);
Cache cache = cacheFactoryBean.getObject();
GemFireCache cache = cacheFactoryBean.getObject();
assertNotNull(cache);

View File

@@ -16,12 +16,14 @@
package org.springframework.data.gemfire.client;
import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNotSame;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.eq;
@@ -31,13 +33,16 @@ import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import java.lang.reflect.Field;
import java.util.Properties;
import org.junit.Test;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanInitializationException;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.data.gemfire.TestUtils;
import org.springframework.data.gemfire.config.GemfireConstants;
import org.springframework.data.util.ReflectionUtils;
import com.gemstone.gemfire.cache.GemFireCache;
import com.gemstone.gemfire.cache.client.ClientCache;
@@ -81,7 +86,7 @@ public class ClientCacheFactoryBeanTest {
Properties gemfireProperties = createProperties("gf", "test");
Properties distributedSystemProperties = createProperties("ds", "mock");
final DistributedSystem mockDistributedSystem = mock(DistributedSystem.class, "MockGemFireDistributedSystem");
final DistributedSystem mockDistributedSystem = mock(DistributedSystem.class, "MockDistributedSystem");
when(mockDistributedSystem.isConnected()).thenReturn(true);
when(mockDistributedSystem.getProperties()).thenReturn(distributedSystemProperties);
@@ -112,7 +117,7 @@ public class ClientCacheFactoryBeanTest {
Properties gemfireProperties = createProperties("gf", "test");
Properties distributedSystemProperties = createProperties("ds", "mock");
final DistributedSystem mockDistributedSystem = mock(DistributedSystem.class, "MockGemFireDistributedSystem");
final DistributedSystem mockDistributedSystem = mock(DistributedSystem.class, "MockDistributedSystem");
when(mockDistributedSystem.isConnected()).thenReturn(false);
when(mockDistributedSystem.getProperties()).thenReturn(distributedSystemProperties);
@@ -410,19 +415,110 @@ public class ClientCacheFactoryBeanTest {
}
@Test
public void postProcessClientCacheAndSignalReadyForEvents() throws Exception {
ClientCache mockClientCache = mock(ClientCache.class, "MockGemFireClientCache");
public void onApplicationEventSignalsReadyForEvents() throws Exception {
ClientCache mockClientCache = mock(ClientCache.class, "MockClientCache");
when(mockClientCache.isClosed()).thenReturn(false);
ClientCacheFactoryBean clientCacheFactoryBean = new ClientCacheFactoryBean();
clientCacheFactoryBean.setReadyForEvents(true);
assertTrue(clientCacheFactoryBean.getReadyForEvents());
assertSame(mockClientCache, clientCacheFactoryBean.postProcess(mockClientCache));
ReflectionUtils.setField(ReflectionUtils.findField(ClientCacheFactoryBean.class,
new org.springframework.util.ReflectionUtils.FieldFilter() {
@Override public boolean matches(final Field field) {
return field.getName().equals("cache");
}
}), clientCacheFactoryBean, mockClientCache);
assertThat(clientCacheFactoryBean.getReadyForEvents(), is(true));
clientCacheFactoryBean.onApplicationEvent(mock(ContextRefreshedEvent.class, "MockContextRefreshedEvent"));
verify(mockClientCache, times(1)).isClosed();
verify(mockClientCache, times(1)).readyForEvents();
}
@Test
public void onApplicationEventDoesNotSignalReadyForEventsWhenClientCacheIsClosed() {
ClientCache mockClientCache = mock(ClientCache.class, "MockClientCache");
when(mockClientCache.isClosed()).thenReturn(true);
ClientCacheFactoryBean clientCacheFactoryBean = new ClientCacheFactoryBean();
clientCacheFactoryBean.setReadyForEvents(true);
ReflectionUtils.setField(ReflectionUtils.findField(ClientCacheFactoryBean.class,
new org.springframework.util.ReflectionUtils.FieldFilter() {
@Override public boolean matches(final Field field) {
return field.getName().equals("cache");
}
}), clientCacheFactoryBean, mockClientCache);
assertThat(clientCacheFactoryBean.getReadyForEvents(), is(true));
clientCacheFactoryBean.onApplicationEvent(mock(ContextRefreshedEvent.class, "MockContextRefreshedEvent"));
verify(mockClientCache, times(1)).isClosed();
verify(mockClientCache, never()).readyForEvents();
}
@Test
public void onApplicationEventDoesNotSignalReadyForEventsWhenClientCacheFactoryBeanReadyForEventsIsFalse() {
ClientCache mockClientCache = mock(ClientCache.class, "MockClientCache");
when(mockClientCache.isClosed()).thenReturn(false);
ClientCacheFactoryBean clientCacheFactoryBean = new ClientCacheFactoryBean();
clientCacheFactoryBean.setReadyForEvents(false);
ReflectionUtils.setField(ReflectionUtils.findField(ClientCacheFactoryBean.class,
new org.springframework.util.ReflectionUtils.FieldFilter() {
@Override public boolean matches(final Field field) {
return field.getName().equals("cache");
}
}), clientCacheFactoryBean, mockClientCache);
assertThat(clientCacheFactoryBean.getReadyForEvents(), is(false));
clientCacheFactoryBean.onApplicationEvent(mock(ContextRefreshedEvent.class, "MockContextRefreshedEvent"));
verify(mockClientCache, never()).isClosed();
verify(mockClientCache, never()).readyForEvents();
}
@Test
public void closeClientCacheWithKeepAlive() {
ClientCache mockClientCache = mock(ClientCache.class, "MockClientCache");
ClientCacheFactoryBean clientCacheFactoryBean = new ClientCacheFactoryBean();
clientCacheFactoryBean.setKeepAlive(true);
assertThat(clientCacheFactoryBean.isKeepAlive(), is(true));
clientCacheFactoryBean.close(mockClientCache);
verify(mockClientCache, times(1)).close(eq(true));
}
@Test
public void closeClientCacheWithoutKeepAlive() {
ClientCache mockClientCache = mock(ClientCache.class, "MockClientCache");
ClientCacheFactoryBean clientCacheFactoryBean = new ClientCacheFactoryBean();
clientCacheFactoryBean.setKeepAlive(false);
assertThat(clientCacheFactoryBean.isKeepAlive(), is(false));
clientCacheFactoryBean.close(mockClientCache);
verify(mockClientCache, times(1)).close(eq(false));
}
@Test
public void autoReconnectDisabled() {
assertFalse(new ClientCacheFactoryBean().getEnableAutoReconnect());

View File

@@ -15,13 +15,18 @@
*/
package org.springframework.data.gemfire.client;
import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.CoreMatchers.notNullValue;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyString;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
@@ -43,6 +48,7 @@ import com.gemstone.gemfire.cache.EvictionAttributes;
import com.gemstone.gemfire.cache.ExpirationAttributes;
import com.gemstone.gemfire.cache.Region;
import com.gemstone.gemfire.cache.RegionAttributes;
import com.gemstone.gemfire.cache.RegionService;
import com.gemstone.gemfire.cache.client.ClientCache;
import com.gemstone.gemfire.cache.client.ClientRegionFactory;
import com.gemstone.gemfire.cache.client.ClientRegionShortcut;
@@ -187,7 +193,8 @@ public class ClientRegionFactoryBeanTest {
ClientRegionFactory<Object, Object> mockClientRegionFactory = mock(ClientRegionFactory.class);
Region<Object, Object> mockRegion = mock(Region.class);
when(mockClientCache.createClientRegionFactory(eq(ClientRegionShortcut.CACHING_PROXY))).thenReturn(mockClientRegionFactory);
when(mockClientCache.createClientRegionFactory(eq(ClientRegionShortcut.CACHING_PROXY))).thenReturn(
mockClientRegionFactory);
when(mockClientRegionFactory.create(eq("TestRegion"))).thenReturn(mockRegion);
factoryBean.setAttributes(null);
@@ -523,4 +530,146 @@ public class ClientRegionFactoryBeanTest {
assertEquals(ClientRegionShortcut.LOCAL_PERSISTENT, factoryBean.resolveClientRegionShortcut());
}
protected <K> Interest<K> newInterest(K key) {
return new Interest<K>(key);
}
protected <K> Interest<K>[] toArray(Interest<K>... interests) {
return interests;
}
@Test
@SuppressWarnings("unchecked")
public void destroyCallsRegionClose() throws Exception {
final Region mockRegion = mock(Region.class, "MockRegion");
RegionService mockRegionService = mock(RegionService.class, "MockRegionService");
when(mockRegion.getRegionService()).thenReturn(mockRegionService);
when(mockRegionService.isClosed()).thenReturn(false);
ClientRegionFactoryBean clientRegionFactoryBean = new ClientRegionFactoryBean() {
@Override public Region getObject() throws Exception {
return mockRegion;
}
};
clientRegionFactoryBean.setClose(true);
clientRegionFactoryBean.setInterests(toArray(newInterest("test")));
assertThat(clientRegionFactoryBean.isClose(), is(true));
assertThat(clientRegionFactoryBean.isDestroy(), is(false));
assertThat(clientRegionFactoryBean.getInterests(), is(notNullValue()));
assertThat(clientRegionFactoryBean.getInterests().length, is(equalTo(1)));
clientRegionFactoryBean.destroy();
verify(mockRegion, times(1)).getRegionService();
verify(mockRegionService, times(1)).isClosed();
verify(mockRegion, times(1)).close();
verify(mockRegion, never()).destroyRegion();
verify(mockRegion, never()).unregisterInterest(any());
verify(mockRegion, never()).unregisterInterestRegex(anyString());
}
@Test
@SuppressWarnings("unchecked")
public void destroyCallsRegionDestroy() throws Exception {
final Region mockRegion = mock(Region.class, "MockRegion");
RegionService mockRegionService = mock(RegionService.class, "MockRegionService");
when(mockRegion.getRegionService()).thenReturn(mockRegionService);
when(mockRegionService.isClosed()).thenReturn(false);
ClientRegionFactoryBean clientRegionFactoryBean = new ClientRegionFactoryBean() {
@Override public Region getObject() throws Exception {
return mockRegion;
}
};
clientRegionFactoryBean.setClose(false);
clientRegionFactoryBean.setDestroy(true);
clientRegionFactoryBean.setInterests(toArray(newInterest("test")));
assertThat(clientRegionFactoryBean.isClose(), is(false));
assertThat(clientRegionFactoryBean.isDestroy(), is(true));
assertThat(clientRegionFactoryBean.getInterests(), is(notNullValue()));
assertThat(clientRegionFactoryBean.getInterests().length, is(equalTo(1)));
clientRegionFactoryBean.destroy();
verify(mockRegion, never()).getRegionService();
verify(mockRegionService, never()).isClosed();
verify(mockRegion, never()).close();
verify(mockRegion, times(1)).destroyRegion();
verify(mockRegion, never()).unregisterInterest(any());
verify(mockRegion, never()).unregisterInterestRegex(anyString());
}
@Test
@SuppressWarnings("unchecked")
public void destroyDoesNothingWhenClientRegionFactoryBeanCloseIsTrueButRegionServiceIsClosed() throws Exception {
final Region mockRegion = mock(Region.class, "MockRegion");
RegionService mockRegionService = mock(RegionService.class, "MockRegionService");
when(mockRegion.getRegionService()).thenReturn(mockRegionService);
when(mockRegionService.isClosed()).thenReturn(true);
ClientRegionFactoryBean clientRegionFactoryBean = new ClientRegionFactoryBean() {
@Override public Region getObject() throws Exception {
return mockRegion;
}
};
clientRegionFactoryBean.setClose(true);
clientRegionFactoryBean.setInterests(toArray(newInterest("test")));
assertThat(clientRegionFactoryBean.isClose(), is(true));
assertThat(clientRegionFactoryBean.isDestroy(), is(false));
assertThat(clientRegionFactoryBean.getInterests(), is(notNullValue()));
assertThat(clientRegionFactoryBean.getInterests().length, is(equalTo(1)));
clientRegionFactoryBean.destroy();
verify(mockRegion, times(1)).getRegionService();
verify(mockRegionService, times(1)).isClosed();
verify(mockRegion, never()).close();
verify(mockRegion, never()).destroyRegion();
verify(mockRegion, never()).unregisterInterest(any());
verify(mockRegion, never()).unregisterInterestRegex(anyString());
}
@Test
@SuppressWarnings("unchecked")
public void destroyDoesNothingWhenClientRegionFactoryBeanCloseAndDestroyAreFalse() throws Exception {
final Region mockRegion = mock(Region.class, "MockRegion");
ClientRegionFactoryBean clientRegionFactoryBean = new ClientRegionFactoryBean() {
@Override public Region getObject() throws Exception {
return mockRegion;
}
};
clientRegionFactoryBean.destroy();
verify(mockRegion, never()).getRegionService();
verify(mockRegion, never()).close();
verify(mockRegion, never()).destroyRegion();
verify(mockRegion, never()).unregisterInterest(any());
verify(mockRegion, never()).unregisterInterestRegex(anyString());
}
@Test
public void destroyDoesNothingWhenRegionIsNull() throws Exception {
ClientRegionFactoryBean clientRegionFactoryBean = new ClientRegionFactoryBean() {
@Override public Region getObject() throws Exception {
return null;
}
};
clientRegionFactoryBean.destroy();
}
}

View File

@@ -0,0 +1,291 @@
/*
* 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.client;
import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.CoreMatchers.notNullValue;
import static org.junit.Assert.assertThat;
import static org.junit.Assume.assumeThat;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import javax.annotation.Resource;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.data.gemfire.GemfireUtils;
import org.springframework.data.gemfire.process.ProcessWrapper;
import org.springframework.data.gemfire.test.AbstractGemFireClientServerIntegrationTest;
import org.springframework.data.gemfire.test.support.ThreadUtils;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.util.Assert;
import com.gemstone.gemfire.cache.DataPolicy;
import com.gemstone.gemfire.cache.EntryEvent;
import com.gemstone.gemfire.cache.Region;
import com.gemstone.gemfire.cache.client.ClientCache;
import com.gemstone.gemfire.cache.client.ClientCacheFactory;
import com.gemstone.gemfire.cache.client.ClientRegionShortcut;
import com.gemstone.gemfire.cache.util.CacheListenerAdapter;
/**
* The DurableClientCacheIntegrationTest class is a test suite of test cases testing GemFire's Durable Client
* functionality in the context of Spring Data GemFire.
*
* @author John Blum
* @see org.junit.Test
* @see org.junit.runner.RunWith
* @see org.springframework.beans.factory.config.BeanPostProcessor
* @see org.springframework.context.ConfigurableApplicationContext
* @see org.springframework.data.gemfire.process.ProcessWrapper
* @see org.springframework.data.gemfire.test.AbstractGemFireClientServerIntegrationTest
* @see org.springframework.test.context.ContextConfiguration
* @see org.springframework.test.context.junit4.SpringJUnit4ClassRunner
* @see com.gemstone.gemfire.cache.client.ClientCache
* @see com.gemstone.gemfire.cache.Region
* @see com.gemstone.gemfire.cache.util.CacheListenerAdapter
* @since 1.6.3
*/
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration
@SuppressWarnings("all")
public class DurableClientCacheIntegrationTest extends AbstractGemFireClientServerIntegrationTest {
private static final int SERVER_PORT = 24842;
private static final AtomicInteger RUN_COUNT = new AtomicInteger(1);
private static List<Integer> regionCacheListenerEventValues =
Collections.synchronizedList(new ArrayList<Integer>(5));
private static ProcessWrapper serverProcess;
private static final String CLIENT_CACHE_INTERESTS_RESULT_POLICY_SYSTEM_PROPERTY =
"gemfire.cache.client.interests.result-policy";
private static final String SERVER_HOST = "localhost";
@Autowired
private ConfigurableApplicationContext applicationContext;
@Autowired
private ClientCache clientCache;
@Resource(name = "Example")
private Region<String, Integer> example;
@BeforeClass
public static void setupGemFireServer() throws IOException {
serverProcess = setupGemFireServer(DurableClientCacheIntegrationTest.class);
}
@AfterClass
public static void tearDownGemFireServer() {
tearDownGemFireServer(serverProcess);
serverProcess = null;
}
@Before
public void setup() {
assertRegion(example, "Example", DataPolicy.NORMAL);
}
@After
public void tearDown() {
if (RUN_COUNT.get() == 1) {
closeApplicationContext();
runClientCacheProducer();
System.setProperty(CLIENT_CACHE_INTERESTS_RESULT_POLICY_SYSTEM_PROPERTY,
InterestResultPolicyType.NONE.name());
RUN_COUNT.incrementAndGet();
}
regionCacheListenerEventValues.clear();
}
protected void closeApplicationContext() {
applicationContext.close();
assertThat(applicationContext.isRunning(), is(false));
assertThat(applicationContext.isActive(), is(false));
}
protected void runClientCacheProducer() {
try {
ClientCache gemfireClientCache = new ClientCacheFactory()
.addPoolServer(SERVER_HOST, SERVER_PORT)
.set("name", "ClientCacheProducer")
.set("mcast-port", "0")
.set("log-level", "warning")
.create();
Region<String, Integer> exampleRegion = gemfireClientCache.<String, Integer>createClientRegionFactory(
ClientRegionShortcut.PROXY).create("Example");
exampleRegion.put("four", 4);
exampleRegion.put("five", 5);
}
finally {
GemfireUtils.closeClientCache();
}
}
protected void waitForRegionEntryEvents() {
ThreadUtils.timedWait(TimeUnit.SECONDS.toMillis(5), TimeUnit.MILLISECONDS.toMillis(500),
new ThreadUtils.WaitCondition() {
@Override public boolean waiting() {
return (regionCacheListenerEventValues.size() < 2);
}
}
);
}
protected void assertRegion(Region<?, ?> region, String expectedName, DataPolicy expectedDataPolicy) {
assertRegion(region, expectedName, String.format("%1$s%2$s", Region.SEPARATOR, expectedName),
expectedDataPolicy);
}
protected void assertRegion(Region<?, ?> region, String expectedName, String expectedPath, DataPolicy expectedDataPolicy) {
assertThat(region, is(notNullValue()));
assertThat(region.getName(), is(equalTo(expectedName)));
assertThat(region.getFullPath(), is(equalTo(expectedPath)));
assertThat(region.getAttributes(), is(notNullValue()));
assertThat(region.getAttributes().getDataPolicy(), is(equalTo(expectedDataPolicy)));
}
protected void assertRegionContents(Region<?, ?> region, Object... values) {
assertThat(region.size(), is(equalTo(values.length)));
for (Object value : values) {
assertThat(region.containsValue(value), is(true));
}
}
@Test
@DirtiesContext
public void durableClientGetsInitializedWithDataOnServer() {
assumeThat(RUN_COUNT.get(), is(equalTo(1)));
assertRegionContents(example, 1, 2, 3);
assertThat(regionCacheListenerEventValues.isEmpty(), is(true));
}
@Test
public void durableClientGetsUpdatesFromServerWhileClientWasOffline() {
assumeThat(RUN_COUNT.get(), is(equalTo(2)));
assertThat(example.isEmpty(), is(true));
waitForRegionEntryEvents();
assertThat(regionCacheListenerEventValues.size(), is(equalTo(2)));
assertThat(regionCacheListenerEventValues, is(equalTo(Arrays.asList(4, 5))));
assertThat(example.isEmpty(), is(true));
}
public static class ClientCacheBeanPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if (RUN_COUNT.get() == 2 && bean instanceof ClientCache) {
// NOTE pending event count is possibly 3 because it includes the 2 puts from the client cache producer
// as well as the "marker"
assertThat(((ClientCache) bean).getDefaultPool().getPendingEventCount(), is(equalTo(
RUN_COUNT.get() == 1 ? -2 : 3)));
pause(TimeUnit.SECONDS.toMillis(3));
}
return bean;
}
}
public static class RegionDataLoadingBeanPostProcessor<K, V> implements BeanPostProcessor {
private Map<K, V> regionData;
private final String regionName;
public RegionDataLoadingBeanPostProcessor(final String regionName) {
Assert.hasText(regionName, "Region name must be specified");
this.regionName = regionName;
}
public void setRegionData(Map<K, V> regionData) {
this.regionData = regionData;
}
protected Map<K, V> getRegionData() {
Assert.state(regionData != null, "Region data was not properly initialized");
return regionData;
}
protected String getRegionName() {
return regionName;
}
protected void loadData(Region<K, V> region) {
region.putAll(getRegionData());
}
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if (bean instanceof Region) {
Region<K, V> region = (Region) bean;
if (getRegionName().equals(region.getName())) {
loadData(region);
}
}
return bean;
}
}
public static class RegionEntryEventRecordingCacheListener extends CacheListenerAdapter<String, Integer> {
@Override
public void afterCreate(final EntryEvent<String, Integer> event) {
regionCacheListenerEventValues.add(event.getNewValue());
}
}
}

View File

@@ -0,0 +1,80 @@
/*
* 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.hamcrest.CoreMatchers.containsString;
import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertThat;
import java.util.Properties;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.gemfire.TestUtils;
import org.springframework.data.gemfire.client.ClientCacheFactoryBean;
import org.springframework.data.gemfire.test.GemfireTestApplicationContextInitializer;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import com.gemstone.gemfire.pdx.PdxSerializer;
/**
* The ClientCacheNamespaceTest class is a test suite of test cases testing the contract and functionality
* of the Spring Data GemFire ClientCacheParser.
*
* @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
* @since 1.6.3
*/
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(initializers = GemfireTestApplicationContextInitializer.class)
@SuppressWarnings("unused")
public class ClientCacheNamespaceTest {
@Autowired
private ClientCacheFactoryBean clientCacheFactoryBean;
@Autowired
private Properties gemfireProperties;
@Autowired
private PdxSerializer reflectionPdxSerializer;
@Test
public void clientCacheFactoryBeanConfiguration() throws Exception {
assertThat(clientCacheFactoryBean.getCacheXml().toString(), containsString("path/to/bogus/cache.xml"));
assertThat(clientCacheFactoryBean.getProperties(), is(equalTo(gemfireProperties)));
assertThat(clientCacheFactoryBean.isLazyInitialize(), is(true));
assertThat(clientCacheFactoryBean.getCopyOnRead(), is(true));
assertThat(clientCacheFactoryBean.getCriticalHeapPercentage(), is(equalTo(0.85f)));
assertThat(clientCacheFactoryBean.getEvictionHeapPercentage(), is(equalTo(0.65f)));
assertThat((PdxSerializer) clientCacheFactoryBean.getPdxSerializer(), is(equalTo(reflectionPdxSerializer)));
assertThat(clientCacheFactoryBean.getPdxIgnoreUnreadFields(), is(true));
assertThat(clientCacheFactoryBean.getPdxPersistent(), is(false));
assertThat(clientCacheFactoryBean.getPdxReadSerialized(), is(true));
assertThat(clientCacheFactoryBean.isKeepAlive(), is(true));
assertThat(TestUtils.<String>readField("poolName", clientCacheFactoryBean), is(equalTo("serverPool")));
assertThat(clientCacheFactoryBean.getReadyForEvents(), is(false));
}
}

View File

@@ -55,9 +55,7 @@ public class ServerProcess {
throw e;
}
finally {
if (applicationContext != null) {
applicationContext.close();
}
close(applicationContext);
}
}
@@ -65,4 +63,13 @@ public class ServerProcess {
return ServerProcess.class.getSimpleName().toLowerCase().concat(".pid");
}
protected static boolean close(final ConfigurableApplicationContext applicationContext) {
if (applicationContext != null) {
applicationContext.close();
return !(applicationContext.isRunning() || applicationContext.isActive());
}
return true;
}
}

View File

@@ -0,0 +1,109 @@
/*
* 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.test;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;
import org.springframework.data.gemfire.fork.ServerProcess;
import org.springframework.data.gemfire.process.ProcessExecutor;
import org.springframework.data.gemfire.process.ProcessWrapper;
import org.springframework.data.gemfire.test.support.FileSystemUtils;
import org.springframework.data.gemfire.test.support.ThreadUtils;
import org.springframework.util.Assert;
/**
* The AbstractGemFireClientServerIntegrationTest class is an abstract test suite base class encapsulating functionality
* common to all test classes implementing GemFire client/server test cases.
*
* @author John Blum
* @see org.springframework.data.gemfire.fork.ServerProcess
* @see org.springframework.data.gemfire.process.ProcessExecutor
* @see org.springframework.data.gemfire.process.ProcessWrapper
* @since 1.8.0
*/
@SuppressWarnings("unused")
public abstract class AbstractGemFireClientServerIntegrationTest {
protected static long DEFAULT_WAIT_TIME_FOR_SERVER_TO_START = TimeUnit.SECONDS.toMillis(20);
protected static long FIVE_HUNDRED_MILLISECONDS = TimeUnit.MILLISECONDS.toMillis(500);
protected static long ONE_SECOND_IN_MILLISECONDS = TimeUnit.SECONDS.toMillis(1);
protected static String PROCESS_WORKING_DIRECTORY_CLEAN_SYSTEM_PROPERTY = "spring.gemfire.force.clean";
protected static void pause(final long duration) {
ThreadUtils.timedWait(Math.max(duration, ONE_SECOND_IN_MILLISECONDS), ONE_SECOND_IN_MILLISECONDS,
new ThreadUtils.WaitCondition() {
@Override public boolean waiting() {
return true;
}
}
);
}
protected static ProcessWrapper setupGemFireServer(final Class<?> testClass) throws IOException {
return setupGemFireServer(testClass, DEFAULT_WAIT_TIME_FOR_SERVER_TO_START);
}
protected static ProcessWrapper setupGemFireServer(final Class<?> testClass, final long waitTimeInMilliseconds) throws IOException {
String serverName = testClass.getSimpleName() + "Server";
File serverWorkingDirectory = new File(FileSystemUtils.WORKING_DIRECTORY, serverName.toLowerCase());
Assert.isTrue(serverWorkingDirectory.isDirectory() || serverWorkingDirectory.mkdirs());
List<String> arguments = new ArrayList<String>();
arguments.add(String.format("-Dgemfire.name=%1$s", serverName));
arguments.add("/".concat(testClass.getName().replace(".", "/").concat("-server-context.xml")));
ProcessWrapper serverProcess = ProcessExecutor.launch(serverWorkingDirectory, ServerProcess.class,
arguments.toArray(new String[arguments.size()]));
waitForServerToStart(serverProcess, waitTimeInMilliseconds);
System.out.printf("The Spring-based, GemFire Cache Server process for %1$s should be running...%n",
testClass.getSimpleName());
return serverProcess;
}
static void waitForServerToStart(final ProcessWrapper process, final long duration) {
ThreadUtils.timedWait(Math.max(duration, FIVE_HUNDRED_MILLISECONDS), FIVE_HUNDRED_MILLISECONDS,
new ThreadUtils.WaitCondition() {
private File processPidControlFile = new File(process.getWorkingDirectory(),
ServerProcess.getServerProcessControlFilename());
@Override public boolean waiting() {
return !processPidControlFile.isFile();
}
}
);
}
protected static void tearDownGemFireServer(final ProcessWrapper process) {
process.shutdown();
if (Boolean.valueOf(System.getProperty(PROCESS_WORKING_DIRECTORY_CLEAN_SYSTEM_PROPERTY, Boolean.TRUE.toString()))) {
org.springframework.util.FileSystemUtils.deleteRecursively(process.getWorkingDirectory());
}
}
}

View File

@@ -29,32 +29,36 @@ public class MockClientCacheFactoryBean extends ClientCacheFactoryBean {
this.cache = new StubCache();
}
public MockClientCacheFactoryBean(ClientCacheFactoryBean cacheFactoryBean) {
public MockClientCacheFactoryBean(ClientCacheFactoryBean clientCacheFactoryBean) {
this();
if (cacheFactoryBean != null) {
this.beanFactoryLocator = cacheFactoryBean.getBeanFactoryLocator();
this.beanClassLoader = cacheFactoryBean.getBeanClassLoader();
this.beanFactory = cacheFactoryBean.getBeanFactory();
this.beanName = cacheFactoryBean.getBeanName();
this.cacheXml = cacheFactoryBean.getCacheXml();
this.copyOnRead = cacheFactoryBean.getCopyOnRead();
this.criticalHeapPercentage = cacheFactoryBean.getCriticalHeapPercentage();
this.dynamicRegionSupport = cacheFactoryBean.getDynamicRegionSupport();
this.evictionHeapPercentage = cacheFactoryBean.getEvictionHeapPercentage();
this.gatewayConflictResolver = cacheFactoryBean.getGatewayConflictResolver();
this.jndiDataSources = cacheFactoryBean.getJndiDataSources();
this.lockLease = cacheFactoryBean.getLockLease();
this.lockTimeout = cacheFactoryBean.getLockTimeout();
this.messageSyncInterval = cacheFactoryBean.getMessageSyncInterval();
this.pdxDiskStoreName = cacheFactoryBean.getPdxDiskStoreName();
this.pdxIgnoreUnreadFields = cacheFactoryBean.getPdxIgnoreUnreadFields();
this.pdxPersistent = cacheFactoryBean.getPdxPersistent();
this.pdxSerializer = cacheFactoryBean.getPdxSerializer();
this.properties = cacheFactoryBean.getProperties();
this.readyForEvents = cacheFactoryBean.getReadyForEvents();
this.searchTimeout = cacheFactoryBean.getSearchTimeout();
this.transactionListeners = cacheFactoryBean.getTransactionListeners();
this.transactionWriter = cacheFactoryBean.getTransactionWriter();
if (clientCacheFactoryBean != null) {
this.beanFactoryLocator = clientCacheFactoryBean.getBeanFactoryLocator();
this.beanClassLoader = clientCacheFactoryBean.getBeanClassLoader();
this.beanFactory = clientCacheFactoryBean.getBeanFactory();
this.beanName = clientCacheFactoryBean.getBeanName();
this.cacheXml = clientCacheFactoryBean.getCacheXml();
this.copyOnRead = clientCacheFactoryBean.getCopyOnRead();
this.criticalHeapPercentage = clientCacheFactoryBean.getCriticalHeapPercentage();
this.dynamicRegionSupport = clientCacheFactoryBean.getDynamicRegionSupport();
this.evictionHeapPercentage = clientCacheFactoryBean.getEvictionHeapPercentage();
this.gatewayConflictResolver = clientCacheFactoryBean.getGatewayConflictResolver();
this.jndiDataSources = clientCacheFactoryBean.getJndiDataSources();
this.keepAlive = clientCacheFactoryBean.isKeepAlive();
this.lockLease = clientCacheFactoryBean.getLockLease();
this.lockTimeout = clientCacheFactoryBean.getLockTimeout();
this.messageSyncInterval = clientCacheFactoryBean.getMessageSyncInterval();
this.pdxDiskStoreName = clientCacheFactoryBean.getPdxDiskStoreName();
this.pdxIgnoreUnreadFields = clientCacheFactoryBean.getPdxIgnoreUnreadFields();
this.pdxPersistent = clientCacheFactoryBean.getPdxPersistent();
this.pdxReadSerialized = clientCacheFactoryBean.getPdxReadSerialized();
this.pdxSerializer = clientCacheFactoryBean.getPdxSerializer();
this.poolName = clientCacheFactoryBean.getPoolName();
this.properties = clientCacheFactoryBean.getProperties();
this.readyForEvents = clientCacheFactoryBean.getReadyForEvents();
this.searchTimeout = clientCacheFactoryBean.getSearchTimeout();
this.transactionListeners = clientCacheFactoryBean.getTransactionListeners();
this.transactionWriter = clientCacheFactoryBean.getTransactionWriter();
}
}

View File

@@ -38,22 +38,22 @@ public abstract class ThreadUtils {
}
}
public static void timedWait(final long milliseconds) {
timedWait(milliseconds, milliseconds);
public static void timedWait(final long duration) {
timedWait(duration, duration);
}
public static void timedWait(final long milliseconds, final long interval) {
timedWait(milliseconds, interval, new WaitCondition() {
public static void timedWait(final long duration, final long interval) {
timedWait(duration, interval, new WaitCondition() {
@Override public boolean waiting() {
return true;
}
});
}
public static void timedWait(final long milliseconds, long interval, final WaitCondition waitCondition) {
final long timeout = (System.currentTimeMillis() + milliseconds);
public static void timedWait(final long duration, long interval, final WaitCondition waitCondition) {
final long timeout = (System.currentTimeMillis() + duration);
interval = Math.min(interval, milliseconds);
interval = Math.min(interval, duration);
while (waitCondition.waiting() && (System.currentTimeMillis() < timeout)) {
try {

View File

@@ -12,7 +12,7 @@
<util:properties id="gemfireProperties">
<prop key="name">BasicSubRegionConfig</prop>
<prop key="mcast-port">0</prop>
<prop key="log-level">config</prop>
<prop key="log-level">warning</prop>
</util:properties>
<gfe:cache properties-ref="gemfireProperties" use-bean-factory-locator="false"/>

View File

@@ -0,0 +1,45 @@
<?xml version="1.0" encoding="utf-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:gfe="http://www.springframework.org/schema/gemfire"
xmlns:util="http://www.springframework.org/schema/util"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/gemfire http://www.springframework.org/schema/gemfire/spring-gemfire.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd
">
<util:properties id="clientProperties">
<prop key="gemfire.cache.client.server.host">localhost</prop>
<prop key="gemfire.cache.client.server.port">24842</prop>
</util:properties>
<context:property-placeholder properties-ref="clientProperties"/>
<bean class="org.springframework.data.gemfire.client.DurableClientCacheIntegrationTest$ClientCacheBeanPostProcessor"/>
<util:properties id="gemfireProperties">
<prop key="durable-client-id">DurableClientCacheIntegrationTestClientId</prop>
<prop key="durable-client-timeout">300</prop>
<prop key="log-level">warning</prop>
<prop key="mcast-port">0</prop>
<prop key="name">DurableClientCacheIntegrationTestClient</prop>
</util:properties>
<gfe:pool id="gemfireServerPool" keep-alive="true" subscription-enabled="true">
<gfe:server host="${gemfire.cache.client.server.host}" port="${gemfire.cache.client.server.port}"/>
</gfe:pool>
<gfe:client-cache properties-ref="gemfireProperties" keep-alive="true" pool-name="gemfireServerPool" ready-for-events="true"
use-bean-factory-locator="false"/>
<gfe:client-region id="Example" pool-name="gemfireServerPool" shortcut="CACHING_PROXY">
<gfe:cache-listener>
<bean class="org.springframework.data.gemfire.client.DurableClientCacheIntegrationTest.RegionEntryEventRecordingCacheListener"/>
</gfe:cache-listener>
<gfe:regex-interest durable="true" pattern= ".*" result-policy="${gemfire.cache.client.interests.result-policy:KEYS_VALUES}"/>
</gfe:client-region>
</beans>

View File

@@ -0,0 +1,50 @@
<?xml version="1.0" encoding="utf-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:c="http://www.springframework.org/schema/c"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:gfe="http://www.springframework.org/schema/gemfire"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:util="http://www.springframework.org/schema/util"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/gemfire http://www.springframework.org/schema/gemfire/spring-gemfire.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd
">
<util:properties id="serverProperties">
<prop key="gemfire.cache.server.host">localhost</prop>
<prop key="gemfire.cache.server.port">24842</prop>
</util:properties>
<context:property-placeholder properties-ref="serverProperties"/>
<util:properties id="gemfireProperties">
<prop key="name">DurableClientCacheIntegrationTestServer</prop>
<prop key="mcast-port">0</prop>
<prop key="log-level">warning</prop>
</util:properties>
<gfe:cache properties-ref="gemfireProperties"/>
<gfe:cache-server bind-address="${gemfire.cache.server.host}" port="${gemfire.cache.server.port}" auto-startup="true"/>
<gfe:replicated-region id="Example" persistent="false" initial-capacity="11" load-factor="0.75"
key-constraint="java.lang.String" value-constraint="java.lang.Integer"/>
<!-- The GemfireTemplate bean definition is required to trigger the creation of the actual '/Example' Region bean
by the SDG RegionFactoryBean in order for the RegionDataLoadingBeanPostProcessor callback to initialize
the '/Example' Region with data. -->
<bean class="org.springframework.data.gemfire.GemfireTemplate" p:region-ref="Example"/>
<util:map id="exampleRegionData" key-type="java.lang.String" value-type="java.lang.Integer">
<entry key="one" value="1"/>
<entry key="two" value="2"/>
<entry key="three" value="3"/>
</util:map>
<bean class="org.springframework.data.gemfire.client.DurableClientCacheIntegrationTest$RegionDataLoadingBeanPostProcessor"
c:regionName="Example" p:regionData-ref="exampleRegionData"/>
</beans>

View File

@@ -0,0 +1,29 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:gfe="http://www.springframework.org/schema/gemfire"
xmlns:util="http://www.springframework.org/schema/util"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/gemfire http://www.springframework.org/schema/gemfire/spring-gemfire.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd
">
<util:properties id="gemfireProperties">
<prop key="name">ClientCacheNamespaceTest</prop>
<prop key="mcast-port">0</prop>
<prop key="log-level">warning</prop>
</util:properties>
<gfe:pool id="serverPool">
<gfe:server host="localhost" port="1234"/>
</gfe:pool>
<bean id="reflectionPdxSerializer" class="com.gemstone.gemfire.pdx.ReflectionBasedAutoSerializer"/>
<gfe:client-cache cache-xml-location="/path/to/bogus/cache.xml" properties-ref="gemfireProperties" lazy-init="true"
copy-on-read="true" critical-heap-percentage="0.85" eviction-heap-percentage="0.65"
pdx-serializer-ref="reflectionPdxSerializer" pdx-ignore-unread-fields="true" pdx-persistent="false"
pdx-read-serialized="true" keep-alive="true" pool-name="serverPool" ready-for-events="false"/>
</beans>