Implement Region entry event triggers for CacheListeners, CacheLoaders and CacheWriters.

This commit is contained in:
John Blum
2019-06-14 18:45:05 -07:00
parent 0b01f6b240
commit 570fcce9eb
3 changed files with 639 additions and 88 deletions

View File

@@ -27,6 +27,7 @@ import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.when;
import static org.mockito.Mockito.withSettings;
import static org.springframework.data.gemfire.tests.util.IOUtils.doSafeIo;
import static org.springframework.data.gemfire.tests.util.ObjectUtils.rethrowAsRuntimeException;
import static org.springframework.data.gemfire.util.ArrayUtils.nullSafeArray;
@@ -50,6 +51,7 @@ import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Properties;
import java.util.Set;
@@ -74,16 +76,19 @@ import org.apache.geode.cache.CacheFactory;
import org.apache.geode.cache.CacheListener;
import org.apache.geode.cache.CacheLoader;
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.DiskStore;
import org.apache.geode.cache.DiskStoreFactory;
import org.apache.geode.cache.EntryEvent;
import org.apache.geode.cache.EntryNotFoundException;
import org.apache.geode.cache.EvictionAttributes;
import org.apache.geode.cache.EvictionAttributesMutator;
import org.apache.geode.cache.ExpirationAction;
import org.apache.geode.cache.ExpirationAttributes;
import org.apache.geode.cache.GemFireCache;
import org.apache.geode.cache.LoaderHelper;
import org.apache.geode.cache.PartitionAttributes;
import org.apache.geode.cache.Region;
import org.apache.geode.cache.RegionAttributes;
@@ -787,7 +792,7 @@ public abstract class GemFireMockObjectsSupport extends MockObjectsSupport {
.thenAnswer(newSetter(batchTimeInterval, mockAsyncEventQueueFactory));
when(mockAsyncEventQueueFactory.setDiskStoreName(anyString()))
.thenAnswer(newSetter(diskStoreName, mockAsyncEventQueueFactory));
.thenAnswer(newSetter(diskStoreName, () -> mockAsyncEventQueueFactory));
when(mockAsyncEventQueueFactory.setDiskSynchronous(anyBoolean()))
.thenAnswer(newSetter(diskSynchronous, mockAsyncEventQueueFactory));
@@ -799,13 +804,13 @@ public abstract class GemFireMockObjectsSupport extends MockObjectsSupport {
.thenAnswer(newSetter(forwardExpirationDestroy, mockAsyncEventQueueFactory));
when(mockAsyncEventQueueFactory.setGatewayEventSubstitutionListener(any(GatewayEventSubstitutionFilter.class)))
.thenAnswer(newSetter(gatewayEventSubstitutionFilter, mockAsyncEventQueueFactory));
.thenAnswer(newSetter(gatewayEventSubstitutionFilter, () -> mockAsyncEventQueueFactory));
when(mockAsyncEventQueueFactory.setMaximumQueueMemory(anyInt()))
.thenAnswer(newSetter(maximumQueueMemory, mockAsyncEventQueueFactory));
when(mockAsyncEventQueueFactory.setOrderPolicy(any(GatewaySender.OrderPolicy.class)))
.thenAnswer(newSetter(orderPolicy, mockAsyncEventQueueFactory));
.thenAnswer(newSetter(orderPolicy, () -> mockAsyncEventQueueFactory));
when(mockAsyncEventQueueFactory.setParallel(anyBoolean()))
.thenAnswer(newSetter(parallel, mockAsyncEventQueueFactory));
@@ -882,10 +887,10 @@ public abstract class GemFireMockObjectsSupport extends MockObjectsSupport {
AtomicReference<String> hostnameForClients = new AtomicReference<>(CacheServer.DEFAULT_HOSTNAME_FOR_CLIENTS);
AtomicReference<ServerLoadProbe> serverLoadProbe = new AtomicReference<>(null);
doAnswer(newSetter(bindAddress, null))
doAnswer(newSetter(bindAddress, () -> null))
.when(mockCacheServer).setBindAddress(anyString());
doAnswer(newSetter(hostnameForClients, null))
doAnswer(newSetter(hostnameForClients, () -> null))
.when(mockCacheServer).setHostnameForClients(anyString());
doAnswer(newSetter(loadPollInterval, null))
@@ -909,7 +914,7 @@ public abstract class GemFireMockObjectsSupport extends MockObjectsSupport {
doAnswer(newSetter(port, null))
.when(mockCacheServer).setPort(anyInt());
doAnswer(newSetter(serverLoadProbe, null))
doAnswer(newSetter(serverLoadProbe, () -> null))
.when(mockCacheServer).setLoadProbe(any(ServerLoadProbe.class));
doAnswer(newSetter(socketBufferSize, null))
@@ -1048,7 +1053,7 @@ public abstract class GemFireMockObjectsSupport extends MockObjectsSupport {
.thenAnswer(newSetter(cloningEnabled, mockClientRegionFactory));
when(mockClientRegionFactory.setCompressor(any(Compressor.class)))
.thenAnswer(newSetter(compressor, mockClientRegionFactory));
.thenAnswer(newSetter(compressor, () -> mockClientRegionFactory));
doAnswer(newSetter(concurrencyChecksEnabled, mockClientRegionFactory))
.when(mockClientRegionFactory).setConcurrencyChecksEnabled(anyBoolean());
@@ -1057,49 +1062,49 @@ public abstract class GemFireMockObjectsSupport extends MockObjectsSupport {
.thenAnswer(newSetter(concurrencyLevel, mockClientRegionFactory));
when(mockClientRegionFactory.setCustomEntryIdleTimeout(any(CustomExpiry.class)))
.thenAnswer(newSetter(customEntryIdleTimeout, mockClientRegionFactory));
.thenAnswer(newSetter(customEntryIdleTimeout, () -> mockClientRegionFactory));
when(mockClientRegionFactory.setCustomEntryTimeToLive(any(CustomExpiry.class)))
.thenAnswer(newSetter(customEntryTimeToLive, mockClientRegionFactory));
.thenAnswer(newSetter(customEntryTimeToLive, () -> mockClientRegionFactory));
when(mockClientRegionFactory.setDiskStoreName(anyString()))
.thenAnswer(newSetter(diskStoreName, mockClientRegionFactory));
.thenAnswer(newSetter(diskStoreName, () -> mockClientRegionFactory));
when(mockClientRegionFactory.setDiskSynchronous(anyBoolean()))
.thenAnswer(newSetter(diskSynchronous, mockClientRegionFactory));
when(mockClientRegionFactory.setEntryIdleTimeout(any(ExpirationAttributes.class)))
.thenAnswer(newSetter(entryIdleTimeout, mockClientRegionFactory));
.thenAnswer(newSetter(entryIdleTimeout, () -> mockClientRegionFactory));
when(mockClientRegionFactory.setEntryTimeToLive(any(ExpirationAttributes.class)))
.thenAnswer(newSetter(entryTimeToLive, mockClientRegionFactory));
.thenAnswer(newSetter(entryTimeToLive, () -> mockClientRegionFactory));
when(mockClientRegionFactory.setEvictionAttributes(any(EvictionAttributes.class)))
.thenAnswer(newSetter(evictionAttributes, mockClientRegionFactory));
.thenAnswer(newSetter(evictionAttributes, () -> mockClientRegionFactory));
when(mockClientRegionFactory.setInitialCapacity(anyInt()))
.thenAnswer(newSetter(initialCapacity, mockClientRegionFactory));
when(mockClientRegionFactory.setKeyConstraint(any(Class.class)))
.thenAnswer(newSetter(keyConstraint, mockClientRegionFactory));
.thenAnswer(newSetter(keyConstraint, () -> mockClientRegionFactory));
when(mockClientRegionFactory.setLoadFactor(anyFloat()))
.thenAnswer(newSetter(loadFactor, mockClientRegionFactory));
.thenAnswer(newSetter(loadFactor, () -> mockClientRegionFactory));
when(mockClientRegionFactory.setPoolName(anyString()))
.thenAnswer(newSetter(poolName, mockClientRegionFactory));
.thenAnswer(newSetter(poolName, () -> mockClientRegionFactory));
when(mockClientRegionFactory.setRegionIdleTimeout(any(ExpirationAttributes.class)))
.thenAnswer(newSetter(regionIdleTimeout, mockClientRegionFactory));
.thenAnswer(newSetter(regionIdleTimeout, () -> mockClientRegionFactory));
when(mockClientRegionFactory.setRegionTimeToLive(any(ExpirationAttributes.class)))
.thenAnswer(newSetter(regionTimeToLive, mockClientRegionFactory));
.thenAnswer(newSetter(regionTimeToLive, () -> mockClientRegionFactory));
when(mockClientRegionFactory.setStatisticsEnabled(anyBoolean()))
.thenAnswer(newSetter(statisticsEnabled, mockClientRegionFactory));
when(mockClientRegionFactory.setValueConstraint(any(Class.class)))
.thenAnswer(newSetter(valueConstraint, mockClientRegionFactory));
.thenAnswer(newSetter(valueConstraint, () -> mockClientRegionFactory));
RegionAttributes<K, V> mockRegionAttributes =
mock(RegionAttributes.class, mockObjectIdentifier("MockRegionAttributes"));
@@ -1157,7 +1162,7 @@ public abstract class GemFireMockObjectsSupport extends MockObjectsSupport {
doAnswer(newSetter(subscriptionCapacity, null))
.when(mockClientSubscriptionConfig).setCapacity(anyInt());
doAnswer(newSetter(subscriptionDiskStoreName, null))
doAnswer(newSetter(subscriptionDiskStoreName, () -> null))
.when(mockClientSubscriptionConfig).setDiskStoreName(anyString());
doAnswer(newSetter(subscriptionEvictionPolicy, stringToSubscriptionEvictionPolicyConverter, null))
@@ -1228,10 +1233,10 @@ public abstract class GemFireMockObjectsSupport extends MockObjectsSupport {
});
when(mockDiskStoreFactory.setDiskUsageCriticalPercentage(anyFloat()))
.thenAnswer(newSetter(diskUsageCriticalPercentage, mockDiskStoreFactory));
.thenAnswer(newSetter(diskUsageCriticalPercentage, () -> mockDiskStoreFactory));
when(mockDiskStoreFactory.setDiskUsageWarningPercentage(anyFloat()))
.thenAnswer(newSetter(diskUsageWarningPercentage, mockDiskStoreFactory));
.thenAnswer(newSetter(diskUsageWarningPercentage, () -> mockDiskStoreFactory));
when(mockDiskStoreFactory.setMaxOplogSize(anyLong()))
.thenAnswer(newSetter(maxOplogSize, mockDiskStoreFactory));
@@ -1325,13 +1330,13 @@ public abstract class GemFireMockObjectsSupport extends MockObjectsSupport {
CopyOnWriteArrayList<GatewayTransportFilter> gatewayTransportFilters = new CopyOnWriteArrayList<>();
when(mockGatewayReceiverFactory.setBindAddress(anyString()))
.thenAnswer(newSetter(bindAddress, mockGatewayReceiverFactory));
.thenAnswer(newSetter(bindAddress, () -> mockGatewayReceiverFactory));
when(mockGatewayReceiverFactory.setEndPort(anyInt()))
.thenAnswer(newSetter(endPort, mockGatewayReceiverFactory));
when(mockGatewayReceiverFactory.setHostnameForSenders(anyString()))
.thenAnswer(newSetter(hostnameForSenders, mockGatewayReceiverFactory));
.thenAnswer(newSetter(hostnameForSenders, () -> mockGatewayReceiverFactory));
when(mockGatewayReceiverFactory.setManualStart(anyBoolean()))
.thenAnswer(newSetter(manualStart, mockGatewayReceiverFactory));
@@ -1433,7 +1438,7 @@ public abstract class GemFireMockObjectsSupport extends MockObjectsSupport {
.thenAnswer(newSetter(batchTimeInterval, mockGatewaySenderFactory));
when(mockGatewaySenderFactory.setDiskStoreName(anyString()))
.thenAnswer(newSetter(diskStoreName, mockGatewaySenderFactory));
.thenAnswer(newSetter(diskStoreName, () -> mockGatewaySenderFactory));
when(mockGatewaySenderFactory.setDiskSynchronous(anyBoolean()))
.thenAnswer(newSetter(diskSynchronous, mockGatewaySenderFactory));
@@ -1442,13 +1447,13 @@ public abstract class GemFireMockObjectsSupport extends MockObjectsSupport {
.thenAnswer(newSetter(dispatcherThreads, mockGatewaySenderFactory));
when(mockGatewaySenderFactory.setGatewayEventSubstitutionFilter(any(GatewayEventSubstitutionFilter.class)))
.thenAnswer(newSetter(gatewayEventSubstitutionFilter, mockGatewaySenderFactory));
.thenAnswer(newSetter(gatewayEventSubstitutionFilter, () -> mockGatewaySenderFactory));
when(mockGatewaySenderFactory.setMaximumQueueMemory(anyInt()))
.thenAnswer(newSetter(maximumQueueMemory, mockGatewaySenderFactory));
when(mockGatewaySenderFactory.setOrderPolicy(any(GatewaySender.OrderPolicy.class)))
.thenAnswer(newSetter(orderPolicy, mockGatewaySenderFactory));
.thenAnswer(newSetter(orderPolicy, () -> mockGatewaySenderFactory));
when(mockGatewaySenderFactory.setParallel(anyBoolean())).thenAnswer(newSetter(parallel, mockGatewaySenderFactory));
@@ -1624,7 +1629,7 @@ public abstract class GemFireMockObjectsSupport extends MockObjectsSupport {
.thenAnswer(newSetter(retryAttempts, mockPoolFactory));
when(mockPoolFactory.setServerGroup(anyString()))
.thenAnswer(newSetter(serverGroup, mockPoolFactory));
.thenAnswer(newSetter(serverGroup, () -> mockPoolFactory));
when(mockPoolFactory.setSocketBufferSize(anyInt()))
.thenAnswer(newSetter(socketBufferSize, mockPoolFactory));
@@ -2168,14 +2173,13 @@ public abstract class GemFireMockObjectsSupport extends MockObjectsSupport {
Map<K, V> data = new ConcurrentHashMap<>();
Region<K, V> mockRegion = mock(Region.class, name);
Region<K, V> mockRegion = mock(Region.class, withSettings().name(name).lenient());
RegionAttributes<K, V> mockRegionAttributes = mockRegionAttributes(mockRegion, regionAttributes);
Set<K> invalidatedKeys = new HashSet<>();
Set<Region<?, ?>> subRegions = new CopyOnWriteArraySet<>();
when(mockRegion.getAttributes()).thenReturn(mockRegionAttributes);
when(mockRegion.getFullPath()).thenReturn(toRegionPath(name));
when(mockRegion.getName()).thenReturn(toRegionName(name));
when(mockRegion.getRegionService()).thenReturn(regionService);
@@ -2196,15 +2200,33 @@ public abstract class GemFireMockObjectsSupport extends MockObjectsSupport {
when(mockRegion.get(ArgumentMatchers.<K>any())).thenAnswer(invocation -> {
K key = invocation.getArgument(0);
V value = data.get(key);
V value = invalidatedKeys.contains(key) ? null : data.get(key);
if (invalidatedKeys.contains(key)) {
value = null;
if (value == null) {
value = Optional.ofNullable(mockRegionAttributes.getCacheLoader())
.map(cacheLoader -> {
LoaderHelper<K, V> mockLoaderHelper = mock(LoaderHelper.class, withSettings().lenient());
when(mockLoaderHelper.getArgument()).thenReturn(null);
when(mockLoaderHelper.getKey()).thenReturn(key);
when(mockLoaderHelper.getRegion()).thenReturn(mockRegion);
return cacheLoader.load(mockLoaderHelper);
})
.map(loadedValue -> {
data.put(key, loadedValue);
invalidatedKeys.remove(key);
return loadedValue;
})
.orElse(value);
}
// TODO: CacheLoader
Optional.ofNullable(value);
return value;
});
@@ -2231,13 +2253,24 @@ public abstract class GemFireMockObjectsSupport extends MockObjectsSupport {
K key = invocation.getArgument(0);
if (data.containsKey(key)) {
invalidatedKeys.add(key);
}
else {
if (!data.containsKey(key)) {
throw new EntryNotFoundException(String.format("Entry with key [%s] not found", key));
}
if (invalidatedKeys.add(key)) {
EntryEvent<K, V> mockEntryEvent = mock(EntryEvent.class, withSettings().lenient());
when(mockEntryEvent.getKey()).thenReturn(key);
when(mockEntryEvent.getNewValue()).thenReturn(null);
when(mockEntryEvent.getOldValue()).thenReturn(data.get(key));
when(mockEntryEvent.getRegion()).thenReturn(mockRegion);
Arrays.stream(ArrayUtils.nullSafeArray(mockRegionAttributes.getCacheListeners(), CacheListener.class))
.filter(Objects::nonNull)
.forEach(cacheListener -> cacheListener.afterInvalidate(mockEntryEvent));
}
return null;
}).when(mockRegion).invalidate(any());
@@ -2247,8 +2280,50 @@ public abstract class GemFireMockObjectsSupport extends MockObjectsSupport {
K key = invocation.getArgument(0);
V newValue = invocation.getArgument(1);
Assert.notNull(newValue, "Value is required");
boolean entryExists = data.containsKey(key);
EntryEvent<K, V> mockEntryEvent = mock(EntryEvent.class, withSettings().lenient());
V entryEventValue = invalidatedKeys.contains(key) ? null : data.get(key);
when(mockEntryEvent.getKey()).thenReturn(key);
when(mockEntryEvent.getNewValue()).thenReturn(newValue);
when(mockEntryEvent.getOldValue()).thenReturn(entryEventValue);
when(mockEntryEvent.getRegion()).thenReturn(mockRegion);
CacheWriter<K, V> cacheWriter = mockRegionAttributes.getCacheWriter();
if (cacheWriter != null) {
try {
if (entryExists) {
cacheWriter.beforeUpdate(mockEntryEvent);
}
else {
cacheWriter.beforeCreate(mockEntryEvent);
}
}
catch (Throwable cause) {
throw new CacheWriterException("Create/Update Error", cause);
}
}
V existingValue = data.put(key, newValue);
Arrays.stream(ArrayUtils.nullSafeArray(mockRegionAttributes.getCacheListeners(), CacheListener.class))
.filter(Objects::nonNull)
.forEach(cacheListener -> {
if (entryExists) {
cacheListener.afterUpdate(mockEntryEvent);
}
else {
cacheListener.afterCreate(mockEntryEvent);
}
});
return invalidatedKeys.remove(key) ? null : existingValue;
});
@@ -2256,8 +2331,33 @@ public abstract class GemFireMockObjectsSupport extends MockObjectsSupport {
when(mockRegion.remove(any())).thenAnswer(invocation -> {
K key = invocation.getArgument(0);
EntryEvent<K, V> mockEntryEvent = mock(EntryEvent.class, withSettings().lenient());
V entryEventValue = invalidatedKeys.contains(key) ? null : data.get(key);
when(mockEntryEvent.getKey()).thenReturn(key);
when(mockEntryEvent.getNewValue()).thenReturn(null);
when(mockEntryEvent.getOldValue()).thenReturn(entryEventValue);
when(mockEntryEvent.getRegion()).thenReturn(mockRegion);
CacheWriter<K, V> cacheWriter = mockRegionAttributes.getCacheWriter();
if (cacheWriter != null) {
try {
cacheWriter.beforeDestroy(mockEntryEvent);
}
catch (Throwable cause) {
throw new CacheWriterException("Destroy Error", cause);
}
}
V value = data.remove(key);
Arrays.stream(ArrayUtils.nullSafeArray(mockRegionAttributes.getCacheListeners(), CacheListener.class))
.filter(Objects::nonNull)
.forEach(cacheListener -> cacheListener.afterDestroy(mockEntryEvent));
return invalidatedKeys.remove(key) ? null : value;
});
@@ -2282,12 +2382,14 @@ public abstract class GemFireMockObjectsSupport extends MockObjectsSupport {
private static <K, V> RegionAttributes<K, V> mockRegionAttributes(Region<K, V> mockRegion,
RegionAttributes<K, V> baseRegionAttributes) {
AttributesMutator<K, V> mockAttributesMutator = mock(AttributesMutator.class);
AttributesMutator<K, V> mockAttributesMutator = mock(AttributesMutator.class, withSettings().lenient());
EvictionAttributesMutator mockEvictionAttributesMutator = mock(EvictionAttributesMutator.class);
EvictionAttributesMutator mockEvictionAttributesMutator =
mock(EvictionAttributesMutator.class, withSettings().lenient());
RegionAttributes<K, V> mockRegionAttributes = mock(RegionAttributes.class);
RegionAttributes<K, V> mockRegionAttributes = mock(RegionAttributes.class, withSettings().lenient());
when(mockRegion.getAttributes()).thenReturn(mockRegionAttributes);
when(mockRegion.getAttributesMutator()).thenReturn(mockAttributesMutator);
when(mockAttributesMutator.getEvictionAttributesMutator()).thenReturn(mockEvictionAttributesMutator);
when(mockAttributesMutator.getRegion()).thenReturn(mockRegion);
@@ -2357,7 +2459,6 @@ public abstract class GemFireMockObjectsSupport extends MockObjectsSupport {
}).when(mockAttributesMutator).initCacheListeners(any(CacheListener[].class));
doAnswer(invocation -> asyncEventQueueIds.remove(invocation.getArgument(0)))
.when(mockAttributesMutator).removeAsyncEventQueueId(anyString());
@@ -2367,35 +2468,36 @@ public abstract class GemFireMockObjectsSupport extends MockObjectsSupport {
doAnswer(invocation -> gatewaySenderIds.remove(invocation.getArgument(0)))
.when(mockAttributesMutator).removeGatewaySenderId(anyString());
doAnswer(newSetter(cacheLoader, baseRegionAttributes.getCacheLoader()))
doAnswer(newSetter(cacheLoader))
.when(mockAttributesMutator).setCacheLoader(any(CacheLoader.class));
doAnswer(newSetter(cacheWriter, baseRegionAttributes.getCacheWriter()))
doAnswer(newSetter(cacheWriter))
.when(mockAttributesMutator).setCacheWriter(any(CacheWriter.class));
doAnswer(newSetter(cloningEnabled, null))
.when(mockAttributesMutator).setCloningEnabled(anyBoolean());
doAnswer(newSetter(customEntryIdleTimeout, baseRegionAttributes.getCustomEntryIdleTimeout()))
doAnswer(newSetter(customEntryIdleTimeout))
.when(mockAttributesMutator).setCustomEntryIdleTimeout(any(CustomExpiry.class));
doAnswer(newSetter(customEntryTimeToLive, baseRegionAttributes.getCustomEntryTimeToLive()))
doAnswer(newSetter(customEntryTimeToLive))
.when(mockAttributesMutator).setCustomEntryTimeToLive(any(CustomExpiry.class));
doAnswer(newSetter(entryIdleTimeout, baseRegionAttributes.getEntryIdleTimeout()))
doAnswer(newSetter(entryIdleTimeout))
.when(mockAttributesMutator).setEntryIdleTimeout(any(ExpirationAttributes.class));
doAnswer(newSetter(entryTimeToLive, baseRegionAttributes.getEntryTimeToLive()))
doAnswer(newSetter(entryTimeToLive))
.when(mockAttributesMutator).setEntryTimeToLive(any(ExpirationAttributes.class));
doAnswer(newSetter(regionIdleTimeout, baseRegionAttributes.getRegionIdleTimeout()))
doAnswer(newSetter(regionIdleTimeout))
.when(mockAttributesMutator).setRegionIdleTimeout(any(ExpirationAttributes.class));
doAnswer(newSetter(regionTimeToLive, baseRegionAttributes.getRegionTimeToLive()))
doAnswer(newSetter(regionTimeToLive))
.when(mockAttributesMutator).setRegionTimeToLive(any(ExpirationAttributes.class));
// Mock EvictionAttributesMutator
doAnswer(newSetter(evictionMaximum, null)).when(mockEvictionAttributesMutator).setMaximum(anyInt());
doAnswer(newSetter(evictionMaximum, null))
.when(mockEvictionAttributesMutator).setMaximum(anyInt());
// Mock RegionAttributes
when(mockRegionAttributes.getAsyncEventQueueIds())
@@ -2619,16 +2721,16 @@ public abstract class GemFireMockObjectsSupport extends MockObjectsSupport {
});
when(mockRegionFactory.setCacheLoader(any(CacheLoader.class)))
.thenAnswer(newSetter(cacheLoader, mockRegionFactory));
.thenAnswer(newSetter(cacheLoader, () -> mockRegionFactory));
when(mockRegionFactory.setCacheWriter(any(CacheWriter.class)))
.thenAnswer(newSetter(cacheWriter, mockRegionFactory));
.thenAnswer(newSetter(cacheWriter, () -> mockRegionFactory));
when(mockRegionFactory.setCloningEnabled(anyBoolean()))
.thenAnswer(newSetter(cloningEnabled, mockRegionFactory));
when(mockRegionFactory.setCompressor(any(Compressor.class)))
.thenAnswer(newSetter(compressor, mockRegionFactory));
.thenAnswer(newSetter(compressor, () -> mockRegionFactory));
when(mockRegionFactory.setConcurrencyChecksEnabled(anyBoolean()))
.then(newSetter(concurrencyChecksEnabled, mockRegionFactory));
@@ -2637,15 +2739,16 @@ public abstract class GemFireMockObjectsSupport extends MockObjectsSupport {
.thenAnswer(newSetter(concurrencyLevel, mockRegionFactory));
when(mockRegionFactory.setCustomEntryIdleTimeout(any(CustomExpiry.class)))
.thenAnswer(newSetter(customEntryIdleTimeout, mockRegionFactory));
.thenAnswer(newSetter(customEntryIdleTimeout, () -> mockRegionFactory));
when(mockRegionFactory.setCustomEntryTimeToLive(any(CustomExpiry.class)))
.thenAnswer(newSetter(customEntryTimeToLive, mockRegionFactory));
.thenAnswer(newSetter(customEntryTimeToLive, () -> mockRegionFactory));
when(mockRegionFactory.setDataPolicy(any(DataPolicy.class)))
.thenAnswer(newSetter(dataPolicy, mockRegionFactory));
.thenAnswer(newSetter(dataPolicy, () -> mockRegionFactory));
when(mockRegionFactory.setDiskStoreName(anyString())).thenAnswer(newSetter(diskStoreName, mockRegionFactory));
when(mockRegionFactory.setDiskStoreName(anyString()))
.thenAnswer(newSetter(diskStoreName, () -> mockRegionFactory));
when(mockRegionFactory.setDiskSynchronous(anyBoolean()))
.thenAnswer(newSetter(diskSynchronous, mockRegionFactory));
@@ -2657,13 +2760,13 @@ public abstract class GemFireMockObjectsSupport extends MockObjectsSupport {
.thenAnswer(newSetter(enableSubscriptionConflation, mockRegionFactory));
when(mockRegionFactory.setEntryIdleTimeout(any(ExpirationAttributes.class)))
.thenAnswer(newSetter(entryIdleTimeout, mockRegionFactory));
.thenAnswer(newSetter(entryIdleTimeout, () -> mockRegionFactory));
when(mockRegionFactory.setEntryTimeToLive(any(ExpirationAttributes.class)))
.thenAnswer(newSetter(entryTimeToLive, mockRegionFactory));
.thenAnswer(newSetter(entryTimeToLive, () -> mockRegionFactory));
when(mockRegionFactory.setEvictionAttributes(any(EvictionAttributes.class)))
.thenAnswer(newSetter(evictionAttributes, mockRegionFactory));
.thenAnswer(newSetter(evictionAttributes, () -> mockRegionFactory));
when(mockRegionFactory.setIgnoreJTA(anyBoolean())).thenAnswer(newSetter(ignoreJta, mockRegionFactory));
@@ -2673,9 +2776,9 @@ public abstract class GemFireMockObjectsSupport extends MockObjectsSupport {
when(mockRegionFactory.setInitialCapacity(anyInt())).thenAnswer(newSetter(initialCapacity, mockRegionFactory));
when(mockRegionFactory.setKeyConstraint(any(Class.class)))
.thenAnswer(newSetter(keyConstraint, mockRegionFactory));
.thenAnswer(newSetter(keyConstraint, () -> mockRegionFactory));
when(mockRegionFactory.setLoadFactor(anyFloat())).thenAnswer(newSetter(loadFactor, mockRegionFactory));
when(mockRegionFactory.setLoadFactor(anyFloat())).thenAnswer(newSetter(loadFactor, () -> mockRegionFactory));
when(mockRegionFactory.setLockGrantor(anyBoolean())).thenAnswer(newSetter(lockGrantor, mockRegionFactory));
@@ -2685,26 +2788,26 @@ public abstract class GemFireMockObjectsSupport extends MockObjectsSupport {
when(mockRegionFactory.setOffHeap(anyBoolean())).thenAnswer(newSetter(offHeap, mockRegionFactory));
when(mockRegionFactory.setPartitionAttributes(any(PartitionAttributes.class)))
.thenAnswer(newSetter(partitionAttributes, mockRegionFactory));
.thenAnswer(newSetter(partitionAttributes, () -> mockRegionFactory));
when(mockRegionFactory.setPoolName(anyString())).thenAnswer(newSetter(poolName, mockRegionFactory));
when(mockRegionFactory.setPoolName(anyString())).thenAnswer(newSetter(poolName, () -> mockRegionFactory));
when(mockRegionFactory.setRegionIdleTimeout(any(ExpirationAttributes.class)))
.thenAnswer(newSetter(regionIdleTimeout, mockRegionFactory));
.thenAnswer(newSetter(regionIdleTimeout, () -> mockRegionFactory));
when(mockRegionFactory.setRegionTimeToLive(any(ExpirationAttributes.class)))
.thenAnswer(newSetter(regionTimeToLive, mockRegionFactory));
.thenAnswer(newSetter(regionTimeToLive, () -> mockRegionFactory));
when(mockRegionFactory.setScope(any(Scope.class))).thenAnswer(newSetter(scope, mockRegionFactory));
when(mockRegionFactory.setScope(any(Scope.class))).thenAnswer(newSetter(scope, () -> mockRegionFactory));
when(mockRegionFactory.setStatisticsEnabled(anyBoolean()))
.thenAnswer(newSetter(statisticsEnabled, mockRegionFactory));
when(mockRegionFactory.setSubscriptionAttributes(any(SubscriptionAttributes.class)))
.thenAnswer(newSetter(subscriptionAttributes, mockRegionFactory));
.thenAnswer(newSetter(subscriptionAttributes, () -> mockRegionFactory));
when(mockRegionFactory.setValueConstraint(any(Class.class)))
.thenAnswer(newSetter(valueConstraint, mockRegionFactory));
.thenAnswer(newSetter(valueConstraint, () -> mockRegionFactory));
RegionAttributes<K, V> mockRegionAttributes =
mock(RegionAttributes.class, mockObjectIdentifier("MockRegionAttributes"));
@@ -2771,16 +2874,16 @@ public abstract class GemFireMockObjectsSupport extends MockObjectsSupport {
AtomicReference<Float> evictionOffHeapPercentage = new AtomicReference<>(0.0f);
doAnswer(newSetter(criticalHeapPercentage, null))
doAnswer(newSetter(criticalHeapPercentage, () -> null))
.when(mockResourceManager).setCriticalHeapPercentage(anyFloat());
doAnswer(newSetter(criticalOffHeapPercentage, null))
doAnswer(newSetter(criticalOffHeapPercentage, () -> null))
.when(mockResourceManager).setCriticalOffHeapPercentage(anyFloat());
doAnswer(newSetter(evictionHeapPercentage, null))
doAnswer(newSetter(evictionHeapPercentage, () -> null))
.when(mockResourceManager).setEvictionHeapPercentage(anyFloat());
doAnswer(newSetter(evictionOffHeapPercentage, null))
doAnswer(newSetter(evictionOffHeapPercentage, () -> null))
.when(mockResourceManager).setEvictionOffHeapPercentage(anyFloat());
when(mockResourceManager.getCriticalHeapPercentage()).thenAnswer(newGetter(criticalHeapPercentage));
@@ -2812,7 +2915,7 @@ public abstract class GemFireMockObjectsSupport extends MockObjectsSupport {
AtomicReference<String> pdxDiskStoreName = new AtomicReference<>(null);
AtomicReference<PdxSerializer> pdxSerializer = new AtomicReference<>(null);
doAnswer(newSetter(pdxDiskStoreName, cacheFactorySpy))
doAnswer(newSetter(pdxDiskStoreName, () -> cacheFactorySpy))
.when(cacheFactorySpy).setPdxDiskStore(anyString());
doAnswer(newSetter(pdxIgnoreUnreadFields, cacheFactorySpy))
@@ -2824,7 +2927,7 @@ public abstract class GemFireMockObjectsSupport extends MockObjectsSupport {
doAnswer(newSetter(pdxReadSerialized, cacheFactorySpy))
.when(cacheFactorySpy).setPdxReadSerialized(anyBoolean());
doAnswer(newSetter(pdxSerializer, cacheFactorySpy))
doAnswer(newSetter(pdxSerializer, () -> cacheFactorySpy))
.when(cacheFactorySpy).setPdxSerializer(any(PdxSerializer.class));
when(mockCache.getPdxDiskStore()).thenAnswer(newGetter(pdxDiskStoreName));
@@ -2865,7 +2968,7 @@ public abstract class GemFireMockObjectsSupport extends MockObjectsSupport {
AtomicReference<PdxSerializer> pdxSerializer = new AtomicReference<>(null);
AtomicReference<Pool> defaultPool = new AtomicReference<>(null);
doAnswer(newSetter(pdxDiskStoreName, clientCacheFactorySpy))
doAnswer(newSetter(pdxDiskStoreName, () -> clientCacheFactorySpy))
.when(clientCacheFactorySpy).setPdxDiskStore(anyString());
doAnswer(newSetter(pdxIgnoreUnreadFields, clientCacheFactorySpy))
@@ -2877,7 +2980,7 @@ public abstract class GemFireMockObjectsSupport extends MockObjectsSupport {
doAnswer(newSetter(pdxReadSerialized, clientCacheFactorySpy))
.when(clientCacheFactorySpy).setPdxReadSerialized(anyBoolean());
doAnswer(newSetter(pdxSerializer, clientCacheFactorySpy))
doAnswer(newSetter(pdxSerializer, () -> clientCacheFactorySpy))
.when(clientCacheFactorySpy).setPdxSerializer(any(PdxSerializer.class));
PoolFactory mockPoolFactory = mockPoolFactory();

View File

@@ -36,6 +36,13 @@ import org.springframework.util.StringUtils;
* used in mocking using Mockito.
*
* @author John Blum
* @see java.util.concurrent.atomic.AtomicBoolean
* @see java.util.concurrent.atomic.AtomicInteger
* @see java.util.concurrent.atomic.AtomicLong
* @see java.util.concurrent.atomic.AtomicReference
* @see java.util.function.Consumer
* @see java.util.function.Function
* @see java.util.function.Supplier
* @see org.mockito.invocation.InvocationOnMock
* @see org.mockito.stubbing.Answer
* @since 0.0.1
@@ -144,35 +151,53 @@ public abstract class MockObjectsSupport {
};
}
protected static <T, R> Answer<R> newSetter(AtomicReference<T> argument, R returnValue) {
protected static <T> Answer<T> newSetter(AtomicReference<T> argument) {
return invocation -> argument.getAndSet(invocation.getArgument(0));
}
protected static <T, R> Answer<R> newSetter(AtomicReference<T> argument, Supplier<R> returnValue) {
return invocation -> {
argument.set(invocation.getArgument(0));
return returnValue;
return returnValue.get();
};
}
protected static <T, R> Answer<R> newSetter(AtomicReference<T> argument, T value, R returnValue) {
protected static <T> Answer<T> newSetterWithArument(AtomicReference<T> argument, T value) {
return invocation -> argument.getAndSet(value);
}
protected static <T, R> Answer<R> newSetterWithArgument(AtomicReference<T> argument, T value,
Supplier<R> returnValue) {
return invocation -> {
argument.set(value);
return returnValue;
return returnValue.get();
};
}
protected static <T, R> Answer<R> newSetter(AtomicReference<T> argument, Function<?, T> converter, R returnValue) {
protected static <T> Answer<T> newSetter(AtomicReference<T> argument, Function<?, T> converter) {
return invocation -> argument.getAndSet(converter.apply(invocation.getArgument(0)));
}
protected static <T, R> Answer<R> newSetter(AtomicReference<T> argument, Function<?, T> converter,
Supplier<R> returnValue) {
return invocation -> {
argument.set(converter.apply(invocation.getArgument(0)));
return returnValue;
return returnValue.get();
};
}
protected static <K, V, R> Answer<R> newSetter(Map<K, V> argument, R returnValue) {
protected static <K, V> Answer<V> newSetter(Map<K, V> argument) {
return invocation -> argument.put(invocation.getArgument(0), invocation.getArgument(1));
}
protected static <K, V, R> Answer<R> newSetter(Map<K, V> argument, Supplier<R> returnValue) {
return invocation -> {
argument.put(invocation.getArgument(0), invocation.getArgument(1));
return returnValue;
return returnValue.get();
};
}

View File

@@ -0,0 +1,423 @@
/*
* Copyright 2019 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.tests;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.ArgumentMatchers.isA;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.inOrder;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;
import static org.mockito.Mockito.verifyZeroInteractions;
import static org.mockito.Mockito.when;
import static org.springframework.data.gemfire.util.RuntimeExceptionFactory.newIllegalStateException;
import java.util.concurrent.atomic.AtomicInteger;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InOrder;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;
import org.mockito.stubbing.Answer;
import org.apache.geode.cache.CacheListener;
import org.apache.geode.cache.CacheLoader;
import org.apache.geode.cache.CacheWriter;
import org.apache.geode.cache.CacheWriterException;
import org.apache.geode.cache.EntryEvent;
import org.apache.geode.cache.EntryNotFoundException;
import org.apache.geode.cache.LoaderHelper;
import org.apache.geode.cache.Region;
import org.apache.geode.cache.RegionAttributes;
import org.apache.geode.cache.RegionService;
import org.springframework.data.gemfire.tests.mock.GemFireMockObjectsSupport;
/**
* Unit Tests for Mock {@link Region}.
*
* @author John Blum
* @see org.junit.Test
* @see org.mockito.Mock
* @see org.mockito.Mockito
* @see org.apache.geode.cache.CacheListener
* @see org.apache.geode.cache.CacheLoader
* @see org.apache.geode.cache.CacheWriter
* @see org.apache.geode.cache.EntryEvent
* @see org.apache.geode.cache.Region
* @see org.apache.geode.cache.RegionService
* @since 0.0.3
*/
@RunWith(MockitoJUnitRunner.class)
@SuppressWarnings("unchecked")
public class MockRegionDataAccessOperationsAndEventsUnitTests {
private Region<Object, Object> mockRegion;
@Mock
private RegionAttributes<Object, Object> mockRegionAttributes;
@Mock
private RegionService mockRegionService;
@Before
public void setup() {
this.mockRegion = GemFireMockObjectsSupport.mockRegion(this.mockRegionService,
"MockRegion", this.mockRegionAttributes);
}
@After
public void tearDown() {
GemFireMockObjectsSupport.destroy();
}
@Test
public void putGetRemoveIsSuccessful() {
assertThat(this.mockRegion).doesNotContainKey(1);
assertThat(this.mockRegion).hasSize(0);
assertThat(this.mockRegion.put(1, "test")).isNull();
assertThat(this.mockRegion).containsKey(1);
assertThat(this.mockRegion).hasSize(1);
assertThat(this.mockRegion.get(1)).isEqualTo("test");
assertThat(this.mockRegion).containsKey(1);
assertThat(this.mockRegion).hasSize(1);
assertThat(this.mockRegion.remove(1)).isEqualTo("test");
assertThat(this.mockRegion).doesNotContainKey(1);
assertThat(this.mockRegion).hasSize(0);
}
@Test
public void putInvalidateGetIsSuccessful() {
assertThat(this.mockRegion).hasSize(0);
assertThat(this.mockRegion.put(1, "test"));
assertThat(this.mockRegion).hasSize(1);
this.mockRegion.invalidate(1);
assertThat(this.mockRegion).containsKey(1);
assertThat(this.mockRegion).hasSize(1);
assertThat(this.mockRegion.get(1)).isNull();
}
@Test
public void putGetInvalidateGetPutGetIsSuccessful() {
assertThat(this.mockRegion).hasSize(0);
assertThat(this.mockRegion.put(1, "test"));
assertThat(this.mockRegion).containsKey(1);
assertThat(this.mockRegion).hasSize(1);
assertThat(this.mockRegion.get(1)).isEqualTo("test");
this.mockRegion.invalidate(1);
assertThat(this.mockRegion).containsKey(1);
assertThat(this.mockRegion).hasSize(1);
assertThat(this.mockRegion.get(1)).isNull();
assertThat(this.mockRegion.put(1, "mock")).isNull();
assertThat(this.mockRegion).containsKey(1);
assertThat(this.mockRegion).hasSize(1);
assertThat(this.mockRegion.get(1)).isEqualTo("mock");
}
@Test
public void cacheLoaderLoadsValueOnCacheMiss() {
assertThat(this.mockRegion).doesNotContainKey("key");
assertThat(this.mockRegion).hasSize(0);
assertThat(this.mockRegion.get("key")).isNull();
AtomicInteger counter = new AtomicInteger(0);
CacheLoader<Object, Object> mockCacheLoader = mock(CacheLoader.class);
when(mockCacheLoader.load(any(LoaderHelper.class))).thenAnswer(invocation -> counter.incrementAndGet());
this.mockRegion.getAttributesMutator().setCacheLoader(mockCacheLoader);
assertThat(this.mockRegion.get("key")).isEqualTo(1);
assertThat(this.mockRegion.get("key")).isEqualTo(1);
assertThat(this.mockRegion).containsKey("key");
assertThat(this.mockRegion).hasSize(1);
assertThat(this.mockRegion.remove("key")).isEqualTo(1);
assertThat(this.mockRegion).doesNotContainKey("key");
assertThat(this.mockRegion).hasSize(0);
assertThat(this.mockRegion.get("key")).isEqualTo(2);
assertThat(this.mockRegion).containsKey("key");
assertThat(this.mockRegion).hasSize(1);
this.mockRegion.invalidate("key");
assertThat(this.mockRegion).containsKey("key");
assertThat(this.mockRegion).hasSize(1);
assertThat(this.mockRegion.get("key")).isEqualTo(3);
assertThat(this.mockRegion).containsKey("key");
assertThat(this.mockRegion).hasSize(1);
verify(mockCacheLoader, times(3)).load(isA(LoaderHelper.class));
}
@Test(expected = EntryNotFoundException.class)
public void invalidateWithNonExistingKeyThrowsException() {
try {
this.mockRegion.invalidate(1);
}
catch (EntryNotFoundException expected) {
assertThat(expected).hasMessage("Entry with key [1] not found");
assertThat(expected).hasNoCause();
throw expected;
}
}
@Test
public void invalidateFiresCacheListenerAfterInvalidateEntryEvent() {
assertThat(this.mockRegion.put(1, "test")).isNull();
assertThat(this.mockRegion).containsKey(1);
assertThat(this.mockRegion.get(1)).isEqualTo("test");
CacheListener<Object, Object> mockCacheListener = mock(CacheListener.class);
doAnswer(invocation -> {
EntryEvent<Object, Object> entryEvent = invocation.getArgument(0);
assertThat(entryEvent).isNotNull();
assertThat(entryEvent.getKey()).isEqualTo(1);
assertThat(entryEvent.getNewValue()).isNull();
assertThat(entryEvent.getOldValue()).isEqualTo("test");
assertThat(entryEvent.getRegion()).isEqualTo(this.mockRegion);
return null;
}).when(mockCacheListener).afterInvalidate(any(EntryEvent.class));
this.mockRegion.getAttributesMutator().addCacheListener(mockCacheListener);
this.mockRegion.invalidate(1);
assertThat(this.mockRegion).containsKey(1);
assertThat(this.mockRegion.get(1)).isNull();
this.mockRegion.invalidate(1);
assertThat(this.mockRegion).containsKey(1);
assertThat(this.mockRegion.get(1)).isNull();
verify(mockCacheListener, times(1)).afterInvalidate(isA(EntryEvent.class));
verifyNoMoreInteractions(mockCacheListener);
}
@Test
public void putFiresCacheWriterThenCacheListenersEntryCreateAndUpdateEvents() {
Answer<Void> createEntryEvent = invocation -> {
EntryEvent<Object, Object> entryEvent = invocation.getArgument(0);
assertThat(entryEvent.getKey()).isEqualTo("key");
assertThat(entryEvent.getOldValue()).isNull();
assertThat(entryEvent.getNewValue()).isEqualTo(1);
assertThat(entryEvent.getRegion()).isEqualTo(this.mockRegion);
return null;
};
Answer<Void> updateEntryEvent = invocation -> {
EntryEvent<Object, Object> entryEvent = invocation.getArgument(0);
assertThat(entryEvent.getKey()).isEqualTo("key");
assertThat(entryEvent.getOldValue()).isEqualTo(1);
assertThat(entryEvent.getNewValue()).isEqualTo(2);
assertThat(entryEvent.getRegion()).isEqualTo(this.mockRegion);
return null;
};
CacheListener<Object, Object> mockCacheListener = mock(CacheListener.class);
doAnswer(createEntryEvent).when(mockCacheListener).afterCreate(any(EntryEvent.class));
doAnswer(updateEntryEvent).when(mockCacheListener).afterUpdate(any(EntryEvent.class));
CacheWriter<Object, Object> mockCacheWriter = mock(CacheWriter.class);
doAnswer(createEntryEvent).when(mockCacheWriter).beforeCreate(any(EntryEvent.class));
doAnswer(updateEntryEvent).when(mockCacheWriter).beforeUpdate(any(EntryEvent.class));
this.mockRegion.getAttributesMutator().addCacheListener(mockCacheListener);
this.mockRegion.getAttributesMutator().setCacheWriter(mockCacheWriter);
assertThat(this.mockRegion.put("key", 1)).isNull();
assertThat(this.mockRegion.put("key", 2)).isEqualTo(1);
InOrder ordered = inOrder(this.mockRegion, mockCacheWriter, mockCacheListener);
ordered.verify(this.mockRegion, times(1)).put(eq("key"), eq(1));
ordered.verify(mockCacheWriter, times(1)).beforeCreate(isA(EntryEvent.class));
ordered.verify(mockCacheListener, times(1)).afterCreate(isA(EntryEvent.class));
ordered.verify(this.mockRegion, times(1)).put(eq("key"), eq(2));
ordered.verify(mockCacheWriter, times(1)).beforeUpdate(isA(EntryEvent.class));
ordered.verify(mockCacheListener, times(1)).afterUpdate(isA(EntryEvent.class));
verifyNoMoreInteractions(mockCacheListener);
verifyNoMoreInteractions(mockCacheWriter);
}
@Test(expected = IllegalArgumentException.class)
public void putNullValue() {
try {
this.mockRegion.put(1, null);
}
catch (IllegalArgumentException expected) {
assertThat(expected).hasMessage("Value is required");
assertThat(expected).hasNoCause();
throw expected;
}
}
@Test(expected = CacheWriterException.class)
public void putStoppedByCacheWriterException() {
CacheListener<Object, Object> mockCacheListener = mock(CacheListener.class);
CacheWriter<Object, Object> mockCacheWriter = mock(CacheWriter.class);
doThrow(newIllegalStateException("TEST")).when(mockCacheWriter).beforeCreate(any(EntryEvent.class));
this.mockRegion.getAttributesMutator().addCacheListener(mockCacheListener);
this.mockRegion.getAttributesMutator().setCacheWriter(mockCacheWriter);
try {
this.mockRegion.put(1, "test");
}
catch (CacheWriterException cause) {
assertThat(cause).hasMessage("Create/Update Error");
assertThat(cause).hasCauseInstanceOf(IllegalStateException.class);
assertThat(cause.getCause()).hasMessage("TEST");
assertThat(cause.getCause()).hasNoCause();
throw cause;
}
finally {
assertThat(this.mockRegion).doesNotContainKey(1);
assertThat(this.mockRegion).hasSize(0);
verify(mockCacheWriter, times(1)).beforeCreate(isA(EntryEvent.class));
verifyZeroInteractions(mockCacheListener);
}
}
@Test
public void removeFiresCacheWriterThenCacheListenerEntryDestroyEvent() {
Answer<Void> destroyEntryEvent = invocation -> {
EntryEvent<Object, Object> entryEvent = invocation.getArgument(0);
assertThat(entryEvent.getKey()).isEqualTo(1);
assertThat(entryEvent.getNewValue()).isNull();
assertThat(entryEvent.getOldValue()).isEqualTo("test");
assertThat(entryEvent.getRegion()).isEqualTo(this.mockRegion);
return null;
};
CacheListener<Object, Object> mockCacheListener = mock(CacheListener.class);
doAnswer(destroyEntryEvent).when(mockCacheListener).afterDestroy(any(EntryEvent.class));
CacheWriter<Object, Object> mockCacheWriter = mock(CacheWriter.class);
doAnswer(destroyEntryEvent).when(mockCacheWriter).beforeDestroy(any(EntryEvent.class));
assertThat(this.mockRegion.put(1, "test")).isNull();
assertThat(this.mockRegion).containsKey(1);
assertThat(this.mockRegion).hasSize(1);
this.mockRegion.getAttributesMutator().addCacheListener(mockCacheListener);
this.mockRegion.getAttributesMutator().setCacheWriter(mockCacheWriter);
assertThat(this.mockRegion.remove(1)).isEqualTo("test");
assertThat(this.mockRegion).doesNotContainKey(1);
assertThat(this.mockRegion).hasSize(0);
InOrder ordered = inOrder(this.mockRegion, mockCacheWriter, mockCacheListener);
ordered.verify(this.mockRegion, times(1)).remove(eq(1));
ordered.verify(mockCacheWriter, times(1)).beforeDestroy(isA(EntryEvent.class));
ordered.verify(mockCacheListener, times(1)).afterDestroy(isA(EntryEvent.class));
verifyNoMoreInteractions(mockCacheListener);
verifyNoMoreInteractions(mockCacheWriter);
}
@Test(expected = CacheWriterException.class)
public void removeStoppedByCacheWriterException() {
CacheListener<Object, Object> mockCacheListener = mock(CacheListener.class);
CacheWriter<Object, Object> mockCacheWriter = mock(CacheWriter.class);
doThrow(newIllegalStateException("TEST")).when(mockCacheWriter).beforeDestroy(any(EntryEvent.class));
assertThat(this.mockRegion.put(1, "test")).isNull();
assertThat(this.mockRegion).containsKey(1);
assertThat(this.mockRegion).hasSize(1);
this.mockRegion.getAttributesMutator().addCacheListener(mockCacheListener);
this.mockRegion.getAttributesMutator().setCacheWriter(mockCacheWriter);
try {
this.mockRegion.remove(1);
}
catch (CacheWriterException expected) {
assertThat(expected).hasMessage("Destroy Error");
assertThat(expected).hasCauseInstanceOf(IllegalStateException.class);
assertThat(expected.getCause()).hasMessage("TEST");
assertThat(expected.getCause()).hasNoCause();
throw expected;
}
finally {
assertThat(this.mockRegion).containsKey(1);
assertThat(this.mockRegion).hasSize(1);
verify(mockCacheWriter, times(1)).beforeDestroy(isA(EntryEvent.class));
verifyZeroInteractions(mockCacheListener);
}
}
}