From 0b01f6b240ba8914e17de4a5dbbfab649dd3ea9d Mon Sep 17 00:00:00 2001 From: John Blum Date: Fri, 14 Jun 2019 14:37:11 -0700 Subject: [PATCH] Implement additional Region data access operations. Implement Region.invalidate(key). Implement Region.remove(key). Re-implement Region.get(key), Region.getEntry(key) and Region.put(key) to handle invalidated keys (Region entries). --- .../tests/mock/GemFireMockObjectsSupport.java | 78 +++++++++++++++++-- ...lientCacheApplicationIntegrationTests.java | 8 ++ 2 files changed, 80 insertions(+), 6 deletions(-) diff --git a/spring-data-geode-test/src/main/java/org/springframework/data/gemfire/tests/mock/GemFireMockObjectsSupport.java b/spring-data-geode-test/src/main/java/org/springframework/data/gemfire/tests/mock/GemFireMockObjectsSupport.java index 66a0c53..4efb721 100644 --- a/spring-data-geode-test/src/main/java/org/springframework/data/gemfire/tests/mock/GemFireMockObjectsSupport.java +++ b/spring-data-geode-test/src/main/java/org/springframework/data/gemfire/tests/mock/GemFireMockObjectsSupport.java @@ -78,6 +78,7 @@ 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.EntryNotFoundException; import org.apache.geode.cache.EvictionAttributes; import org.apache.geode.cache.EvictionAttributesMutator; import org.apache.geode.cache.ExpirationAction; @@ -2171,6 +2172,7 @@ public abstract class GemFireMockObjectsSupport extends MockObjectsSupport { RegionAttributes mockRegionAttributes = mockRegionAttributes(mockRegion, regionAttributes); + Set invalidatedKeys = new HashSet<>(); Set> subRegions = new CopyOnWriteArraySet<>(); when(mockRegion.getAttributes()).thenReturn(mockRegionAttributes); @@ -2186,16 +2188,80 @@ public abstract class GemFireMockObjectsSupport extends MockObjectsSupport { return regions.get(subRegionFullPath); }); - when(mockRegion.get(ArgumentMatchers.any())).thenAnswer(invocation -> - data.get(invocation.getArgument(0))); + // Region.containsKey(key) + when(mockRegion.containsKey(any())).thenAnswer(invocation -> + data.containsKey(invocation.getArgument(0))); - when(mockRegion.getEntry(ArgumentMatchers.any())).thenAnswer(invocation -> - data.entrySet().stream().filter(entry -> entry.getKey().equals(invocation.getArgument(0))).findFirst() + // Region.get(key) + when(mockRegion.get(ArgumentMatchers.any())).thenAnswer(invocation -> { + + K key = invocation.getArgument(0); + V value = data.get(key); + + if (invalidatedKeys.contains(key)) { + value = null; + } + + // TODO: CacheLoader + Optional.ofNullable(value); + + return value; + }); + + // Region.getEntry(key) + when(mockRegion.getEntry(ArgumentMatchers.any())).thenAnswer(regionGetEntryInvocation -> + data.entrySet().stream() + .filter(entry -> entry.getKey().equals(regionGetEntryInvocation.getArgument(0))) + .findFirst() + .map(entry -> { + + Map.Entry entrySpy = spy(entry); + + doAnswer(entryGetValueInvocation -> + invalidatedKeys.contains(entry.getKey()) ? null : entry.getValue()) + .when(entrySpy).getValue(); + + return entrySpy; + + }) .orElse(null)); - when(mockRegion.put(any(), any())).thenAnswer(invocation -> - data.put(invocation.getArgument(0), invocation.getArgument(1))); + // Region.invalidate(key) + doAnswer(invocation -> { + K key = invocation.getArgument(0); + + if (data.containsKey(key)) { + invalidatedKeys.add(key); + } + else { + throw new EntryNotFoundException(String.format("Entry with key [%s] not found", key)); + } + + return null; + + }).when(mockRegion).invalidate(any()); + + // Region.put(key, value) + when(mockRegion.put(any(), any())).thenAnswer(invocation -> { + + K key = invocation.getArgument(0); + V newValue = invocation.getArgument(1); + V existingValue = data.put(key, newValue); + + return invalidatedKeys.remove(key) ? null : existingValue; + }); + + // Region.remove(key) + when(mockRegion.remove(any())).thenAnswer(invocation -> { + + K key = invocation.getArgument(0); + V value = data.remove(key); + + return invalidatedKeys.remove(key) ? null : value; + }); + + // Region.size() when(mockRegion.size()).thenAnswer(invocation -> data.size()); when(mockRegion.subregions(anyBoolean())).thenAnswer(invocation -> { diff --git a/spring-data-geode-test/src/test/java/org/springframework/data/gemfire/MockClientCacheApplicationIntegrationTests.java b/spring-data-geode-test/src/test/java/org/springframework/data/gemfire/MockClientCacheApplicationIntegrationTests.java index 7f9b490..73e0c21 100644 --- a/spring-data-geode-test/src/test/java/org/springframework/data/gemfire/MockClientCacheApplicationIntegrationTests.java +++ b/spring-data-geode-test/src/test/java/org/springframework/data/gemfire/MockClientCacheApplicationIntegrationTests.java @@ -89,6 +89,14 @@ public class MockClientCacheApplicationIntegrationTests { assertThat(this.example.getName()).isEqualTo("Example"); assertThat(this.example.put(1, "test")).isNull(); assertThat(this.example.get(1)).isEqualTo("test"); + assertThat(this.example.containsKey(1)).isTrue(); + + this.example.invalidate(1); + + assertThat(this.example.containsKey(1)).isTrue(); + assertThat(this.example.get(1)).isNull(); + assertThat(this.example.remove(1)).isNull(); + assertThat(this.example.containsKey(1)).isFalse(); } @ClientCacheApplication