This is an automated email from the ASF dual-hosted git repository.

dschneider pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/geode.git


The following commit(s) were added to refs/heads/develop by this push:
     new 4f0c0b1  GEODE-4333: add unit tests for AbstractRegionMap.destroy 
(#1314)
4f0c0b1 is described below

commit 4f0c0b1f32d86aad4595c33c679e20799c5dbaeb
Author: Darrel Schneider <dschnei...@pivotal.io>
AuthorDate: Mon Jan 22 11:21:53 2018 -0800

    GEODE-4333: add unit tests for AbstractRegionMap.destroy (#1314)
---
 .../geode/internal/cache/AbstractRegionMap.java    |   3 +-
 .../geode/internal/cache/VMLRURegionMap.java       |   8 +-
 .../internal/cache/AbstractRegionMapTest.java      | 720 +++++++++++++++++++--
 3 files changed, 657 insertions(+), 74 deletions(-)

diff --git 
a/geode-core/src/main/java/org/apache/geode/internal/cache/AbstractRegionMap.java
 
b/geode-core/src/main/java/org/apache/geode/internal/cache/AbstractRegionMap.java
index 487c35a..0b3329e 100644
--- 
a/geode-core/src/main/java/org/apache/geode/internal/cache/AbstractRegionMap.java
+++ 
b/geode-core/src/main/java/org/apache/geode/internal/cache/AbstractRegionMap.java
@@ -1083,8 +1083,7 @@ public abstract class AbstractRegionMap implements 
RegionMap {
         // I'm avoiding indenting just to preserve the ability
         // to track diffs since the code is fairly complex.
 
-        RegionEntry re =
-            getOrCreateRegionEntry(owner, event, Token.REMOVED_PHASE1, null, 
true, true);
+        RegionEntry re = getEntry(event);
         RegionEntry tombstone = null;
         boolean haveTombstone = false;
         /*
diff --git 
a/geode-core/src/main/java/org/apache/geode/internal/cache/VMLRURegionMap.java 
b/geode-core/src/main/java/org/apache/geode/internal/cache/VMLRURegionMap.java
index 23d4162..ab916ae 100644
--- 
a/geode-core/src/main/java/org/apache/geode/internal/cache/VMLRURegionMap.java
+++ 
b/geode-core/src/main/java/org/apache/geode/internal/cache/VMLRURegionMap.java
@@ -58,9 +58,15 @@ class VMLRURegionMap extends AbstractRegionMap {
 
   VMLRURegionMap(EvictableRegion owner, Attributes attr,
       InternalRegionArguments internalRegionArgs) {
+    this(owner, attr, internalRegionArgs, createEvictionController(owner, 
internalRegionArgs));
+  }
+
+  /** used by unit tests */
+  VMLRURegionMap(EvictableRegion owner, Attributes attr, 
InternalRegionArguments internalRegionArgs,
+      EvictionController evictionController) {
     super(internalRegionArgs);
     initialize(owner, attr, internalRegionArgs);
-    this.evictionController = createEvictionController(owner, 
internalRegionArgs);
+    this.evictionController = evictionController;
     getEvictionController().setPerEntryOverhead(getEntryOverhead());
     this.lruList = new EvictionListBuilder(getEvictionController()).create();
   }
diff --git 
a/geode-core/src/test/java/org/apache/geode/internal/cache/AbstractRegionMapTest.java
 
b/geode-core/src/test/java/org/apache/geode/internal/cache/AbstractRegionMapTest.java
index a06175a..6885bfd 100644
--- 
a/geode-core/src/test/java/org/apache/geode/internal/cache/AbstractRegionMapTest.java
+++ 
b/geode-core/src/test/java/org/apache/geode/internal/cache/AbstractRegionMapTest.java
@@ -15,15 +15,15 @@
 package org.apache.geode.internal.cache;
 
 import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
-import static org.mockito.Mockito.any;
-import static org.mockito.Mockito.anyBoolean;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.doThrow;
-import static org.mockito.Mockito.eq;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.times;
@@ -33,16 +33,27 @@ import static org.mockito.Mockito.when;
 import org.junit.Test;
 import org.junit.experimental.categories.Category;
 
+import org.apache.geode.cache.CacheWriterException;
 import org.apache.geode.cache.DataPolicy;
 import org.apache.geode.cache.EntryNotFoundException;
+import org.apache.geode.cache.EvictionAttributes;
 import org.apache.geode.cache.Operation;
+import org.apache.geode.cache.TimeoutException;
 import 
org.apache.geode.distributed.internal.membership.InternalDistributedMember;
+import org.apache.geode.internal.cache.eviction.EvictableEntry;
+import org.apache.geode.internal.cache.eviction.EvictionController;
+import org.apache.geode.internal.cache.eviction.EvictionCounters;
+import org.apache.geode.internal.cache.versions.RegionVersionVector;
 import org.apache.geode.internal.cache.versions.VersionHolder;
+import org.apache.geode.internal.cache.versions.VersionTag;
+import org.apache.geode.internal.util.concurrent.CustomEntryConcurrentHashMap;
 import org.apache.geode.test.junit.categories.UnitTest;
 
 @Category(UnitTest.class)
 public class AbstractRegionMapTest {
 
+  private static final Object KEY = "key";
+
   @Test
   public void shouldBeMockable() throws Exception {
     AbstractRegionMap mockAbstractRegionMap = mock(AbstractRegionMap.class);
@@ -60,16 +71,13 @@ public class AbstractRegionMapTest {
   @Test
   public void invalidateOfNonExistentRegionThrowsEntryNotFound() {
     TestableAbstractRegionMap arm = new TestableAbstractRegionMap();
-    EntryEventImpl event = createEventForInvalidate(arm.owner);
-    when(arm.owner.isInitialized()).thenReturn(true);
+    EntryEventImpl event = createEventForInvalidate(arm._getOwner());
+    when(arm._getOwner().isInitialized()).thenReturn(true);
 
-    try {
-      arm.invalidate(event, true, false, false);
-      fail("expected EntryNotFoundException");
-    } catch (EntryNotFoundException expected) {
-    }
-    verify(arm.owner, never()).basicInvalidatePart2(any(), any(), 
anyBoolean(), anyBoolean());
-    verify(arm.owner, never()).invokeInvalidateCallbacks(any(), any(), 
anyBoolean());
+    assertThatThrownBy(() -> arm.invalidate(event, true, false, false))
+        .isInstanceOf(EntryNotFoundException.class);
+    verify(arm._getOwner(), never()).basicInvalidatePart2(any(), any(), 
anyBoolean(), anyBoolean());
+    verify(arm._getOwner(), never()).invokeInvalidateCallbacks(any(), any(), 
anyBoolean());
   }
 
   @Test
@@ -77,16 +85,14 @@ public class AbstractRegionMapTest {
     AbstractRegionMap.FORCE_INVALIDATE_EVENT = true;
     try {
       TestableAbstractRegionMap arm = new TestableAbstractRegionMap();
-      EntryEventImpl event = createEventForInvalidate(arm.owner);
-      when(arm.owner.isInitialized()).thenReturn(true);
-
-      try {
-        arm.invalidate(event, true, false, false);
-        fail("expected EntryNotFoundException");
-      } catch (EntryNotFoundException expected) {
-      }
-      verify(arm.owner, never()).basicInvalidatePart2(any(), any(), 
anyBoolean(), anyBoolean());
-      verify(arm.owner, times(1)).invokeInvalidateCallbacks(any(), any(), 
anyBoolean());
+      EntryEventImpl event = createEventForInvalidate(arm._getOwner());
+      when(arm._getOwner().isInitialized()).thenReturn(true);
+
+      assertThatThrownBy(() -> arm.invalidate(event, true, false, false))
+          .isInstanceOf(EntryNotFoundException.class);
+      verify(arm._getOwner(), never()).basicInvalidatePart2(any(), any(), 
anyBoolean(),
+          anyBoolean());
+      verify(arm._getOwner(), times(1)).invokeInvalidateCallbacks(any(), 
any(), anyBoolean());
     } finally {
       AbstractRegionMap.FORCE_INVALIDATE_EVENT = false;
     }
@@ -95,20 +101,17 @@ public class AbstractRegionMapTest {
   @Test
   public void invalidateOfAlreadyInvalidEntryReturnsFalse() {
     TestableAbstractRegionMap arm = new TestableAbstractRegionMap();
-    EntryEventImpl event = createEventForInvalidate(arm.owner);
+    EntryEventImpl event = createEventForInvalidate(arm._getOwner());
 
     // invalidate on region that is not initialized should create
     // entry in map as invalid.
-    try {
-      arm.invalidate(event, true, false, false);
-      fail("expected EntryNotFoundException");
-    } catch (EntryNotFoundException expected) {
-    }
+    assertThatThrownBy(() -> arm.invalidate(event, true, false, false))
+        .isInstanceOf(EntryNotFoundException.class);
 
-    when(arm.owner.isInitialized()).thenReturn(true);
+    when(arm._getOwner().isInitialized()).thenReturn(true);
     assertFalse(arm.invalidate(event, true, false, false));
-    verify(arm.owner, never()).basicInvalidatePart2(any(), any(), 
anyBoolean(), anyBoolean());
-    verify(arm.owner, never()).invokeInvalidateCallbacks(any(), any(), 
anyBoolean());
+    verify(arm._getOwner(), never()).basicInvalidatePart2(any(), any(), 
anyBoolean(), anyBoolean());
+    verify(arm._getOwner(), never()).invokeInvalidateCallbacks(any(), any(), 
anyBoolean());
   }
 
   @Test
@@ -116,45 +119,49 @@ public class AbstractRegionMapTest {
     AbstractRegionMap.FORCE_INVALIDATE_EVENT = true;
     try {
       TestableAbstractRegionMap arm = new TestableAbstractRegionMap();
-      EntryEventImpl event = createEventForInvalidate(arm.owner);
+      EntryEventImpl event = createEventForInvalidate(arm._getOwner());
 
       // invalidate on region that is not initialized should create
       // entry in map as invalid.
-      try {
-        arm.invalidate(event, true, false, false);
-        fail("expected EntryNotFoundException");
-      } catch (EntryNotFoundException expected) {
-      }
+      assertThatThrownBy(() -> arm.invalidate(event, true, false, false))
+          .isInstanceOf(EntryNotFoundException.class);
 
-      when(arm.owner.isInitialized()).thenReturn(true);
+      when(arm._getOwner().isInitialized()).thenReturn(true);
       assertFalse(arm.invalidate(event, true, false, false));
-      verify(arm.owner, never()).basicInvalidatePart2(any(), any(), 
anyBoolean(), anyBoolean());
-      verify(arm.owner, times(1)).invokeInvalidateCallbacks(any(), any(), 
anyBoolean());
+      verify(arm._getOwner(), never()).basicInvalidatePart2(any(), any(), 
anyBoolean(),
+          anyBoolean());
+      verify(arm._getOwner(), times(1)).invokeInvalidateCallbacks(any(), 
any(), anyBoolean());
     } finally {
       AbstractRegionMap.FORCE_INVALIDATE_EVENT = false;
     }
   }
 
   private EntryEventImpl createEventForInvalidate(LocalRegion lr) {
-    Object key = "key";
-    when(lr.getKeyInfo(key)).thenReturn(new KeyInfo(key, null, null));
-    return EntryEventImpl.create(lr, Operation.INVALIDATE, key, false, null, 
true, false);
+    when(lr.getKeyInfo(KEY)).thenReturn(new KeyInfo(KEY, null, null));
+    return EntryEventImpl.create(lr, Operation.INVALIDATE, KEY, false, null, 
true, false);
+  }
+
+  private EntryEventImpl createEventForDestroy(LocalRegion lr) {
+    when(lr.getKeyInfo(KEY)).thenReturn(new KeyInfo(KEY, null, null));
+    return EntryEventImpl.create(lr, Operation.DESTROY, KEY, false, null, 
true, false);
   }
 
   @Test
   public void invalidateForceNewEntryOfAlreadyInvalidEntryReturnsFalse() {
     TestableAbstractRegionMap arm = new TestableAbstractRegionMap();
-    EntryEventImpl event = createEventForInvalidate(arm.owner);
+    EntryEventImpl event = createEventForInvalidate(arm._getOwner());
 
     // invalidate on region that is not initialized should create
     // entry in map as invalid.
     assertTrue(arm.invalidate(event, true, true, false));
-    verify(arm.owner, times(1)).basicInvalidatePart2(any(), any(), 
anyBoolean(), anyBoolean());
+    verify(arm._getOwner(), times(1)).basicInvalidatePart2(any(), any(), 
anyBoolean(),
+        anyBoolean());
 
-    when(arm.owner.isInitialized()).thenReturn(true);
+    when(arm._getOwner().isInitialized()).thenReturn(true);
     assertFalse(arm.invalidate(event, true, true, false));
-    verify(arm.owner, times(1)).basicInvalidatePart2(any(), any(), 
anyBoolean(), anyBoolean());
-    verify(arm.owner, never()).invokeInvalidateCallbacks(any(), any(), 
anyBoolean());
+    verify(arm._getOwner(), times(1)).basicInvalidatePart2(any(), any(), 
anyBoolean(),
+        anyBoolean());
+    verify(arm._getOwner(), never()).invokeInvalidateCallbacks(any(), any(), 
anyBoolean());
   }
 
   @Test
@@ -162,46 +169,618 @@ public class AbstractRegionMapTest {
     AbstractRegionMap.FORCE_INVALIDATE_EVENT = true;
     try {
       TestableAbstractRegionMap arm = new TestableAbstractRegionMap();
-      EntryEventImpl event = createEventForInvalidate(arm.owner);
+      EntryEventImpl event = createEventForInvalidate(arm._getOwner());
 
       // invalidate on region that is not initialized should create
       // entry in map as invalid.
       assertTrue(arm.invalidate(event, true, true, false));
-      verify(arm.owner, times(1)).basicInvalidatePart2(any(), any(), 
anyBoolean(), anyBoolean());
-      verify(arm.owner, never()).invokeInvalidateCallbacks(any(), any(), 
anyBoolean());
+      verify(arm._getOwner(), times(1)).basicInvalidatePart2(any(), any(), 
anyBoolean(),
+          anyBoolean());
+      verify(arm._getOwner(), never()).invokeInvalidateCallbacks(any(), any(), 
anyBoolean());
 
-      when(arm.owner.isInitialized()).thenReturn(true);
+      when(arm._getOwner().isInitialized()).thenReturn(true);
       assertFalse(arm.invalidate(event, true, true, false));
-      verify(arm.owner, times(1)).basicInvalidatePart2(any(), any(), 
anyBoolean(), anyBoolean());
-      verify(arm.owner, times(1)).invokeInvalidateCallbacks(any(), any(), 
anyBoolean());
+      verify(arm._getOwner(), times(1)).basicInvalidatePart2(any(), any(), 
anyBoolean(),
+          anyBoolean());
+      verify(arm._getOwner(), times(1)).invokeInvalidateCallbacks(any(), 
any(), anyBoolean());
     } finally {
       AbstractRegionMap.FORCE_INVALIDATE_EVENT = false;
     }
   }
 
-  private static class TestableAbstractRegionMap extends AbstractRegionMap {
+  @Test
+  public void destroyWithEmptyRegionThrowsException() {
+    TestableAbstractRegionMap arm = new TestableAbstractRegionMap();
+    EntryEventImpl event = createEventForDestroy(arm._getOwner());
+    assertThatThrownBy(() -> arm.destroy(event, false, false, false, false, 
null, false))
+        .isInstanceOf(EntryNotFoundException.class);
+  }
+
+  @Test
+  public void destroyWithEmptyRegionInTokenModeAddsAToken() {
+    final TestableAbstractRegionMap arm = new TestableAbstractRegionMap();
+    final EntryEventImpl event = createEventForDestroy(arm._getOwner());
+    final Object expectedOldValue = null;
+    final boolean inTokenMode = true;
+    final boolean duringRI = false;
+    assertThat(arm.destroy(event, inTokenMode, duringRI, false, false, 
expectedOldValue, false))
+        .isTrue();
+    assertThat(arm._getMap().containsKey(event.getKey())).isTrue();
+    RegionEntry re = (RegionEntry) arm._getMap().get(event.getKey());
+    assertThat(re.getValueAsToken()).isEqualTo(Token.DESTROYED);
+    boolean invokeCallbacks = true;
+    verify(arm._getOwner(), times(1)).basicDestroyPart2(any(), eq(event), 
eq(inTokenMode),
+        eq(false), eq(duringRI), eq(invokeCallbacks));
+    verify(arm._getOwner(), times(1)).basicDestroyPart3(any(), eq(event), 
eq(inTokenMode),
+        eq(duringRI), eq(invokeCallbacks), eq(expectedOldValue));
+  }
+
+  @Test
+  public void 
destroyWithEmptyRegionInTokenModeWithRegionClearedExceptionDoesDestroy()
+      throws Exception {
+    CustomEntryConcurrentHashMap<String, EvictableEntry> map =
+        mock(CustomEntryConcurrentHashMap.class);
+    EvictableEntry entry = mock(EvictableEntry.class);
+    when(entry.destroy(any(), any(), anyBoolean(), anyBoolean(), any(), 
anyBoolean(), anyBoolean()))
+        .thenThrow(RegionClearedException.class);
+    when(map.get(KEY)).thenReturn(null);
+    RegionEntryFactory factory = mock(RegionEntryFactory.class);
+    when(factory.createEntry(any(), any(), any())).thenReturn(entry);
+    final TestableAbstractRegionMap arm = new TestableAbstractRegionMap(false, 
map, factory);
+    final EntryEventImpl event = createEventForDestroy(arm._getOwner());
+    final Object expectedOldValue = null;
+    final boolean inTokenMode = true;
+    final boolean duringRI = false;
+    assertThat(arm.destroy(event, inTokenMode, duringRI, false, false, 
expectedOldValue, false))
+        .isTrue();
+    boolean invokeCallbacks = true;
+    verify(arm._getOwner(), times(1)).basicDestroyPart2(any(), eq(event), 
eq(inTokenMode), eq(true),
+        eq(duringRI), eq(invokeCallbacks));
+    verify(arm._getOwner(), times(1)).basicDestroyPart3(any(), eq(event), 
eq(inTokenMode),
+        eq(duringRI), eq(invokeCallbacks), eq(expectedOldValue));
+  }
+
+  @Test
+  public void evictDestroyWithEmptyRegionInTokenModeDoesNothing() {
+    final TestableVMLRURegionMap arm = new TestableVMLRURegionMap(true);
+    final EntryEventImpl event = createEventForDestroy(arm._getOwner());
+    final Object expectedOldValue = null;
+    final boolean inTokenMode = true;
+    final boolean duringRI = false;
+    final boolean evict = true;
+    assertThat(arm.destroy(event, inTokenMode, duringRI, false, evict, 
expectedOldValue, false))
+        .isFalse();
+    assertThat(arm._getMap().containsKey(event.getKey())).isFalse();
+    verify(arm._getOwner(), never()).basicDestroyPart2(any(), any(), 
anyBoolean(), anyBoolean(),
+        anyBoolean(), anyBoolean());
+    verify(arm._getOwner(), never()).basicDestroyPart3(any(), any(), 
anyBoolean(), anyBoolean(),
+        anyBoolean(), any());
+  }
+
+  @Test
+  public void 
evictDestroyWithExistingTombstoneInTokenModeChangesToDestroyToken() {
+    final TestableVMLRURegionMap arm = new TestableVMLRURegionMap(true);
+    addEntry(arm, Token.TOMBSTONE);
+    final EntryEventImpl event = createEventForDestroy(arm._getOwner());
+    final Object expectedOldValue = null;
+    final boolean inTokenMode = true;
+    final boolean duringRI = false;
+    final boolean evict = true;
+    assertThat(arm.destroy(event, inTokenMode, duringRI, false, evict, 
expectedOldValue, false))
+        .isTrue();
+    assertThat(arm._getMap().containsKey(event.getKey())).isTrue();
+    RegionEntry re = (RegionEntry) arm._getMap().get(event.getKey());
+    assertThat(re.getValueAsToken()).isEqualTo(Token.DESTROYED);
+    boolean invokeCallbacks = true;
+    verify(arm._getOwner(), times(1)).basicDestroyPart2(any(), eq(event), 
eq(inTokenMode),
+        eq(false), eq(duringRI), eq(invokeCallbacks));
+    verify(arm._getOwner(), times(1)).basicDestroyPart3(any(), eq(event), 
eq(inTokenMode),
+        eq(duringRI), eq(invokeCallbacks), eq(expectedOldValue));
+  }
+
+  @Test
+  public void 
evictDestroyWithExistingTombstoneInUseByTransactionInTokenModeDoesNothing()
+      throws RegionClearedException {
+    CustomEntryConcurrentHashMap<String, EvictableEntry> map =
+        mock(CustomEntryConcurrentHashMap.class);
+    EvictableEntry entry = mock(EvictableEntry.class);
+    when(entry.isInUseByTransaction()).thenReturn(true);
+    when(entry.getValue()).thenReturn(Token.TOMBSTONE);
+    when(map.get(KEY)).thenReturn(entry);
+    final TestableVMLRURegionMap arm = new TestableVMLRURegionMap(true, map);
+    final EntryEventImpl event = createEventForDestroy(arm._getOwner());
+    final Object expectedOldValue = null;
+    final boolean inTokenMode = true;
+    final boolean duringRI = false;
+    final boolean evict = true;
+    assertThat(arm.destroy(event, inTokenMode, duringRI, false, evict, 
expectedOldValue, false))
+        .isFalse();
+    verify(entry, never()).destroy(any(), any(), anyBoolean(), anyBoolean(), 
any(), anyBoolean(),
+        anyBoolean());
+    verify(arm._getOwner(), never()).basicDestroyPart2(any(), any(), 
anyBoolean(), anyBoolean(),
+        anyBoolean(), anyBoolean());
+    verify(arm._getOwner(), never()).basicDestroyPart3(any(), any(), 
anyBoolean(), anyBoolean(),
+        anyBoolean(), any());
+  }
+
+  @Test
+  public void 
evictDestroyWithConcurrentChangeFromNullToInUseByTransactionInTokenModeDoesNothing()
+      throws RegionClearedException {
+    CustomEntryConcurrentHashMap<Object, EvictableEntry> map =
+        mock(CustomEntryConcurrentHashMap.class);
+    EvictableEntry entry = mock(EvictableEntry.class);
+    when(entry.isInUseByTransaction()).thenReturn(true);
+    when(map.get(KEY)).thenReturn(null);
+    when(map.putIfAbsent(eq(KEY), any())).thenReturn(entry);
+    final TestableVMLRURegionMap arm = new TestableVMLRURegionMap(true, map);
+    final EntryEventImpl event = createEventForDestroy(arm._getOwner());
+    final Object expectedOldValue = null;
+    final boolean inTokenMode = true;
+    final boolean duringRI = false;
+    final boolean evict = true;
+    assertThat(arm.destroy(event, inTokenMode, duringRI, false, evict, 
expectedOldValue, false))
+        .isFalse();
+    verify(entry, never()).destroy(any(), any(), anyBoolean(), anyBoolean(), 
any(), anyBoolean(),
+        anyBoolean());
+    verify(arm._getOwner(), never()).basicDestroyPart2(any(), any(), 
anyBoolean(), anyBoolean(),
+        anyBoolean(), anyBoolean());
+    verify(arm._getOwner(), never()).basicDestroyPart3(any(), any(), 
anyBoolean(), anyBoolean(),
+        anyBoolean(), any());
+  }
+
+  @Test
+  public void destroyWithConcurrentChangeFromNullToValidRetriesAndDoesDestroy()
+      throws RegionClearedException {
+    CustomEntryConcurrentHashMap<Object, EvictableEntry> map =
+        mock(CustomEntryConcurrentHashMap.class);
+    EvictableEntry entry = mock(EvictableEntry.class);
+    when(entry.getValue()).thenReturn("value");
+    when(entry.destroy(any(), any(), anyBoolean(), anyBoolean(), any(), 
anyBoolean(), anyBoolean()))
+        .thenReturn(true);
+    when(map.get(KEY)).thenReturn(null).thenReturn(entry);
+    when(map.putIfAbsent(eq(KEY), any())).thenReturn(entry);
+    final TestableVMLRURegionMap arm = new TestableVMLRURegionMap(true, map);
+    final EntryEventImpl event = createEventForDestroy(arm._getOwner());
+    final Object expectedOldValue = null;
+    final boolean inTokenMode = false;
+    final boolean duringRI = false;
+    final boolean evict = false;
+    assertThat(arm.destroy(event, inTokenMode, duringRI, false, evict, 
expectedOldValue, false))
+        .isTrue();
+    verify(entry, times(1)).destroy(eq(arm._getOwner()), eq(event), eq(false), 
anyBoolean(),
+        eq(expectedOldValue), anyBoolean(), anyBoolean());
+    boolean invokeCallbacks = true;
+    verify(arm._getOwner(), times(1)).basicDestroyPart2(any(), eq(event), 
eq(inTokenMode),
+        eq(false), eq(duringRI), eq(invokeCallbacks));
+    verify(arm._getOwner(), times(1)).basicDestroyPart3(any(), eq(event), 
eq(inTokenMode),
+        eq(duringRI), eq(invokeCallbacks), eq(expectedOldValue));
+  }
+
+  @Test
+  public void 
destroyInTokenModeWithConcurrentChangeFromNullToRemovePhase2RetriesAndDoesDestroy()
+      throws RegionClearedException {
+    CustomEntryConcurrentHashMap<Object, EvictableEntry> map =
+        mock(CustomEntryConcurrentHashMap.class);
+    EvictableEntry entry = mock(EvictableEntry.class);
+    when(entry.isRemovedPhase2()).thenReturn(true);
+    when(entry.destroy(any(), any(), anyBoolean(), anyBoolean(), any(), 
anyBoolean(), anyBoolean()))
+        .thenReturn(true);
+    when(map.get(KEY)).thenReturn(null);
+    when(map.putIfAbsent(eq(KEY), any())).thenReturn(entry).thenReturn(null);
+    final TestableVMLRURegionMap arm = new TestableVMLRURegionMap(true, map);
+    final EntryEventImpl event = createEventForDestroy(arm._getOwner());
+    final Object expectedOldValue = null;
+    final boolean inTokenMode = true;
+    final boolean duringRI = false;
+    final boolean evict = false;
+    assertThat(arm.destroy(event, inTokenMode, duringRI, false, evict, 
expectedOldValue, false))
+        .isTrue();
+    verify(map).remove(eq(KEY), eq(entry));
+    verify(map, times(2)).putIfAbsent(eq(KEY), any());
+    verify(entry, never()).destroy(eq(arm._getOwner()), eq(event), eq(false), 
anyBoolean(),
+        eq(expectedOldValue), anyBoolean(), anyBoolean());
+    boolean invokeCallbacks = true;
+    verify(arm._getOwner(), times(1)).basicDestroyPart2(any(), eq(event), 
eq(inTokenMode),
+        eq(false), eq(duringRI), eq(invokeCallbacks));
+    verify(arm._getOwner(), times(1)).basicDestroyPart3(any(), eq(event), 
eq(inTokenMode),
+        eq(duringRI), eq(invokeCallbacks), eq(expectedOldValue));
+  }
+
+  @Test
+  public void 
destroyWithConcurrentChangeFromTombstoneToValidRetriesAndDoesDestroy()
+      throws RegionClearedException {
+    CustomEntryConcurrentHashMap<Object, EvictableEntry> map =
+        mock(CustomEntryConcurrentHashMap.class);
+    EvictableEntry entry = mock(EvictableEntry.class);
+    when(entry.getValue()).thenReturn("value");
+    when(entry.isTombstone()).thenReturn(true).thenReturn(false);
+    when(entry.destroy(any(), any(), anyBoolean(), anyBoolean(), any(), 
anyBoolean(), anyBoolean()))
+        .thenReturn(true);
+    when(map.get(KEY)).thenReturn(entry);
+    final TestableVMLRURegionMap arm = new TestableVMLRURegionMap(true, map);
+    final EntryEventImpl event = createEventForDestroy(arm._getOwner());
+    final Object expectedOldValue = null;
+    final boolean inTokenMode = false;
+    final boolean duringRI = false;
+    final boolean evict = false;
+    assertThat(arm.destroy(event, inTokenMode, duringRI, false, evict, 
expectedOldValue, false))
+        .isTrue();
+    verify(entry, times(1)).destroy(eq(arm._getOwner()), eq(event), eq(false), 
anyBoolean(),
+        eq(expectedOldValue), anyBoolean(), anyBoolean());
+    boolean invokeCallbacks = true;
+    verify(arm._getOwner(), times(1)).basicDestroyPart2(any(), eq(event), 
eq(inTokenMode),
+        eq(false), eq(duringRI), eq(invokeCallbacks));
+    verify(arm._getOwner(), times(1)).basicDestroyPart3(any(), eq(event), 
eq(inTokenMode),
+        eq(duringRI), eq(invokeCallbacks), eq(expectedOldValue));
+  }
+
+  @Test
+  public void destroyOfExistingEntryInTokenModeAddsAToken() {
+    final TestableAbstractRegionMap arm = new TestableAbstractRegionMap();
+    addEntry(arm);
+    final EntryEventImpl event = createEventForDestroy(arm._getOwner());
+    final Object expectedOldValue = null;
+    final boolean inTokenMode = true;
+    final boolean duringRI = false;
+    assertThat(arm.destroy(event, inTokenMode, duringRI, false, false, 
expectedOldValue, false))
+        .isTrue();
+    assertThat(arm._getMap().containsKey(event.getKey())).isTrue();
+    RegionEntry re = (RegionEntry) arm._getMap().get(event.getKey());
+    assertThat(re.getValueAsToken()).isEqualTo(Token.DESTROYED);
+    boolean invokeCallbacks = true;
+    verify(arm._getOwner(), times(1)).basicDestroyPart2(any(), eq(event), 
eq(inTokenMode),
+        eq(false), eq(duringRI), eq(invokeCallbacks));
+    verify(arm._getOwner(), times(1)).basicDestroyPart3(any(), eq(event), 
eq(inTokenMode),
+        eq(duringRI), eq(invokeCallbacks), eq(expectedOldValue));
+  }
+
+  @Test
+  public void 
destroyOfExistingTombstoneInTokenModeWithConcurrencyChecksDoesNothing() {
+    final TestableAbstractRegionMap arm = new TestableAbstractRegionMap(true);
+    RegionVersionVector<?> versionVector = mock(RegionVersionVector.class);
+    when(arm._getOwner().getVersionVector()).thenReturn(versionVector);
+    final EntryEventImpl event = createEventForDestroy(arm._getOwner());
+    VersionTag<?> versionTag = mock(VersionTag.class);
+    when(versionTag.hasValidVersion()).thenReturn(true);
+    event.setVersionTag(versionTag);
+    addEntry(arm, Token.TOMBSTONE);
+    final Object expectedOldValue = null;
+    final boolean inTokenMode = true;
+    final boolean duringRI = false;
+    assertThat(arm.destroy(event, inTokenMode, duringRI, false, false, 
expectedOldValue, false))
+        .isTrue();
+    assertThat(arm._getMap().containsKey(event.getKey())).isTrue();
+    RegionEntry re = (RegionEntry) arm._getMap().get(event.getKey());
+    // why not DESTROY token?
+    assertThat(re.getValueAsToken()).isEqualTo(Token.TOMBSTONE);
+    // since it was already destroyed why do we do the parts?
+    boolean invokeCallbacks = true;
+    verify(arm._getOwner(), times(1)).basicDestroyPart2(any(), eq(event), 
eq(inTokenMode),
+        eq(false), eq(duringRI), eq(invokeCallbacks));
+    verify(arm._getOwner(), times(1)).basicDestroyPart3(any(), eq(event), 
eq(inTokenMode),
+        eq(duringRI), eq(invokeCallbacks), eq(expectedOldValue));
+  }
+
+  @Test
+  public void 
destroyOfExistingTombstoneWithConcurrencyChecksThrowsEntryNotFound() {
+    final TestableAbstractRegionMap arm = new TestableAbstractRegionMap(true);
+    RegionVersionVector<?> versionVector = mock(RegionVersionVector.class);
+    when(arm._getOwner().getVersionVector()).thenReturn(versionVector);
+    final EntryEventImpl event = createEventForDestroy(arm._getOwner());
+    VersionTag<?> versionTag = mock(VersionTag.class);
+    when(versionTag.hasValidVersion()).thenReturn(true);
+    event.setVersionTag(versionTag);
+    addEntry(arm, Token.TOMBSTONE);
+    final Object expectedOldValue = null;
+    final boolean inTokenMode = false;
+    final boolean duringRI = false;
+    assertThatThrownBy(
+        () -> arm.destroy(event, inTokenMode, duringRI, false, false, 
expectedOldValue, false))
+            .isInstanceOf(EntryNotFoundException.class);
+  }
+
+  @Test
+  public void 
destroyOfExistingTombstoneWithConcurrencyChecksAndRemoveRecoveredEntryDoesRemove()
 {
+    final TestableAbstractRegionMap arm = new TestableAbstractRegionMap(true);
+    RegionVersionVector<?> versionVector = mock(RegionVersionVector.class);
+    when(arm._getOwner().getVersionVector()).thenReturn(versionVector);
+    final EntryEventImpl event = createEventForDestroy(arm._getOwner());
+    VersionTag<?> versionTag = mock(VersionTag.class);
+    when(versionTag.hasValidVersion()).thenReturn(true);
+    event.setVersionTag(versionTag);
+    addEntry(arm, Token.TOMBSTONE);
+    final Object expectedOldValue = null;
+    final boolean inTokenMode = false;
+    final boolean duringRI = false;
+    final boolean removeRecoveredEntry = true;
+    assertThat(arm.destroy(event, inTokenMode, duringRI, false, false, 
expectedOldValue,
+        removeRecoveredEntry)).isTrue();
+    assertThat(arm._getMap().containsKey(event.getKey())).isFalse();
+    boolean invokeCallbacks = true;
+    verify(arm._getOwner(), times(1)).basicDestroyPart2(any(), eq(event), 
eq(inTokenMode),
+        eq(false), eq(duringRI), eq(invokeCallbacks));
+    verify(arm._getOwner(), times(1)).basicDestroyPart3(any(), eq(event), 
eq(inTokenMode),
+        eq(duringRI), eq(invokeCallbacks), eq(expectedOldValue));
+  }
+
+  @Test
+  public void 
destroyOfExistingRemovePhase2WithConcurrencyChecksAndRemoveRecoveredEntryDoesRetryAndThrowsEntryNotFound()
 {
+    final TestableAbstractRegionMap arm = new TestableAbstractRegionMap(true);
+    RegionVersionVector<?> versionVector = mock(RegionVersionVector.class);
+    when(arm._getOwner().getVersionVector()).thenReturn(versionVector);
+    final EntryEventImpl event = createEventForDestroy(arm._getOwner());
+    VersionTag<?> versionTag = mock(VersionTag.class);
+    when(versionTag.hasValidVersion()).thenReturn(true);
+    event.setVersionTag(versionTag);
+    addEntry(arm, Token.REMOVED_PHASE2);
+    final Object expectedOldValue = null;
+    final boolean inTokenMode = false;
+    final boolean duringRI = false;
+    final boolean removeRecoveredEntry = true;
+    assertThatThrownBy(() -> arm.destroy(event, inTokenMode, duringRI, false, 
false,
+        expectedOldValue, 
removeRecoveredEntry)).isInstanceOf(EntryNotFoundException.class);
+  }
+
+  @Test
+  public void destroyOfExistingEntryRemovesEntryFromMapAndDoesNotifications() {
+    final TestableAbstractRegionMap arm = new TestableAbstractRegionMap();
+    addEntry(arm);
+    final EntryEventImpl event = createEventForDestroy(arm._getOwner());
+    final Object expectedOldValue = null;
+    final boolean inTokenMode = false;
+    final boolean duringRI = false;
+    assertThat(arm.destroy(event, inTokenMode, duringRI, false, false, 
expectedOldValue, false))
+        .isTrue();
+    assertThat(arm._getMap().containsKey(event.getKey())).isFalse();
+    boolean invokeCallbacks = true;
+    verify(arm._getOwner(), times(1)).basicDestroyPart2(any(), eq(event), 
eq(inTokenMode),
+        eq(false), eq(duringRI), eq(invokeCallbacks));
+    verify(arm._getOwner(), times(1)).basicDestroyPart3(any(), eq(event), 
eq(inTokenMode),
+        eq(duringRI), eq(invokeCallbacks), eq(expectedOldValue));
+  }
+
+  @Test
+  public void 
destroyOfExistingEntryWithConcurrencyChecksAndNoVersionTagDestroysWithoutTombstone()
 {
+    final TestableAbstractRegionMap arm = new TestableAbstractRegionMap(true);
+    addEntry(arm);
+    final EntryEventImpl event = createEventForDestroy(arm._getOwner());
+    final Object expectedOldValue = null;
+    final boolean inTokenMode = false;
+    final boolean duringRI = false;
+    assertThat(arm.destroy(event, inTokenMode, duringRI, false, false, 
expectedOldValue, false))
+        .isTrue();
+    // This might be a bug. It seems like we should have created a tombstone 
but we have no
+    // version tag so that might be the cause of this bug.
+    assertThat(arm._getMap().containsKey(event.getKey())).isFalse();
+    boolean invokeCallbacks = true;
+    verify(arm._getOwner(), times(1)).basicDestroyPart2(any(), eq(event), 
eq(inTokenMode),
+        eq(false), eq(duringRI), eq(invokeCallbacks));
+    verify(arm._getOwner(), times(1)).basicDestroyPart3(any(), eq(event), 
eq(inTokenMode),
+        eq(duringRI), eq(invokeCallbacks), eq(expectedOldValue));
+  }
+
+  @Test
+  public void destroyOfExistingEntryWithConcurrencyChecksAddsTombstone() {
+    final TestableAbstractRegionMap arm = new TestableAbstractRegionMap(true);
+    RegionVersionVector versionVector = mock(RegionVersionVector.class);
+    when(arm._getOwner().getVersionVector()).thenReturn(versionVector);
+    addEntry(arm);
+    final EntryEventImpl event = createEventForDestroy(arm._getOwner());
+    VersionTag versionTag = mock(VersionTag.class);
+    when(versionTag.hasValidVersion()).thenReturn(true);
+    event.setVersionTag(versionTag);
+    final Object expectedOldValue = null;
+    final boolean inTokenMode = false;
+    final boolean duringRI = false;
+    assertThat(arm.destroy(event, inTokenMode, duringRI, false, false, 
expectedOldValue, false))
+        .isTrue();
+    assertThat(arm._getMap().containsKey(event.getKey())).isTrue();
+    RegionEntry re = (RegionEntry) arm._getMap().get(event.getKey());
+    assertThat(re.getValueAsToken()).isEqualTo(Token.TOMBSTONE);
+    boolean invokeCallbacks = true;
+    verify(arm._getOwner(), times(1)).basicDestroyPart2(any(), eq(event), 
eq(inTokenMode),
+        eq(false), eq(duringRI), eq(invokeCallbacks));
+    verify(arm._getOwner(), times(1)).basicDestroyPart3(any(), eq(event), 
eq(inTokenMode),
+        eq(duringRI), eq(invokeCallbacks), eq(expectedOldValue));
+  }
+
+  @Test
+  public void evictDestroyOfExistingEntryWithConcurrencyChecksAddsTombstone() {
+    final TestableVMLRURegionMap arm = new TestableVMLRURegionMap(true);
+    RegionVersionVector<?> versionVector = mock(RegionVersionVector.class);
+    when(arm._getOwner().getVersionVector()).thenReturn(versionVector);
+    addEntry(arm);
+    final EntryEventImpl event = createEventForDestroy(arm._getOwner());
+    VersionTag<?> versionTag = mock(VersionTag.class);
+    when(versionTag.hasValidVersion()).thenReturn(true);
+    event.setVersionTag(versionTag);
+    final Object expectedOldValue = null;
+    final boolean inTokenMode = false;
+    final boolean duringRI = false;
+    final boolean evict = true;
+    assertThat(arm.destroy(event, inTokenMode, duringRI, false, evict, 
expectedOldValue, false))
+        .isTrue();
+    assertThat(arm._getMap().containsKey(event.getKey())).isTrue();
+    RegionEntry re = (RegionEntry) arm._getMap().get(event.getKey());
+    assertThat(re.getValueAsToken()).isEqualTo(Token.TOMBSTONE);
+    boolean invokeCallbacks = true;
+    verify(arm._getOwner(), times(1)).basicDestroyPart2(any(), eq(event), 
eq(inTokenMode),
+        eq(false), eq(duringRI), eq(invokeCallbacks));
+    verify(arm._getOwner(), times(1)).basicDestroyPart3(any(), eq(event), 
eq(inTokenMode),
+        eq(duringRI), eq(invokeCallbacks), eq(expectedOldValue));
+  }
+
+
+  private void addEntry(AbstractRegionMap arm) {
+    addEntry(arm, "value");
+  }
+
+  private void addEntry(AbstractRegionMap arm, Object value) {
+    RegionEntry entry = arm.getEntryFactory().createEntry(arm._getOwner(), 
KEY, value);
+    arm._getMap().put(KEY, entry);
+  }
+
+  @Test
+  public void destroyWithEmptyRegionWithConcurrencyChecksThrowsException() {
+    TestableAbstractRegionMap arm = new TestableAbstractRegionMap(true);
+    EntryEventImpl event = createEventForDestroy(arm._getOwner());
+    assertThatThrownBy(() -> arm.destroy(event, false, false, false, false, 
null, false))
+        .isInstanceOf(EntryNotFoundException.class);
+  }
+
+  @Test
+  public void evictDestroyWithEmptyRegionWithConcurrencyChecksDoesNothing() {
+    final TestableVMLRURegionMap arm = new TestableVMLRURegionMap(true);
+    EntryEventImpl event = createEventForDestroy(arm._getOwner());
+    assertThat(arm.destroy(event, false, false, false, true, null, 
false)).isFalse();
+    verify(arm._getOwner(), never()).basicDestroyPart2(any(), any(), 
anyBoolean(), anyBoolean(),
+        anyBoolean(), anyBoolean());
+    verify(arm._getOwner(), never()).basicDestroyPart3(any(), any(), 
anyBoolean(), anyBoolean(),
+        anyBoolean(), any());
+    // This seems to be a bug. We should not leave an entry in the map
+    // added by the destroy call if destroy returns false.
+    assertThat(arm._getMap().containsKey(event.getKey())).isTrue();
+    RegionEntry re = (RegionEntry) arm._getMap().get(event.getKey());
+    assertThat(re.getValueAsToken()).isEqualTo(Token.REMOVED_PHASE1);
+  }
+
+  @Test
+  public void evictDestroyWithEmptyRegionDoesNothing() {
+    final TestableVMLRURegionMap arm = new TestableVMLRURegionMap(false);
+    EntryEventImpl event = createEventForDestroy(arm._getOwner());
+    assertThat(arm.destroy(event, false, false, false, true, null, 
false)).isFalse();
+    verify(arm._getOwner(), never()).basicDestroyPart2(any(), any(), 
anyBoolean(), anyBoolean(),
+        anyBoolean(), anyBoolean());
+    verify(arm._getOwner(), never()).basicDestroyPart3(any(), any(), 
anyBoolean(), anyBoolean(),
+        anyBoolean(), any());
+    assertThat(arm._getMap().containsKey(event.getKey())).isFalse();
+  }
+
+  @Test
+  public void destroyWithEmptyRegionWithConcurrencyChecksAddsATombstone() {
+    final TestableAbstractRegionMap arm = new TestableAbstractRegionMap(true);
+    RegionVersionVector versionVector = mock(RegionVersionVector.class);
+    when(arm._getOwner().getVersionVector()).thenReturn(versionVector);
+    final EntryEventImpl event = createEventForDestroy(arm._getOwner());
+    VersionTag versionTag = mock(VersionTag.class);
+    when(versionTag.hasValidVersion()).thenReturn(true);
+    event.setVersionTag(versionTag);
+    event.setOriginRemote(true);
+    final Object expectedOldValue = null;
+    final boolean inTokenMode = false;
+    final boolean duringRI = false;
+    assertThat(arm.destroy(event, inTokenMode, duringRI, false, false, 
expectedOldValue, false))
+        .isTrue();
+    assertThat(arm._getMap().containsKey(event.getKey())).isTrue();
+    RegionEntry re = (RegionEntry) arm._getMap().get(event.getKey());
+    assertThat(re.getValueAsToken()).isEqualTo(Token.TOMBSTONE);
+    boolean invokeCallbacks = true;
+    verify(arm._getOwner(), times(1)).basicDestroyPart2(any(), eq(event), 
eq(inTokenMode),
+        eq(false), eq(duringRI), eq(invokeCallbacks));
+    verify(arm._getOwner(), times(1)).basicDestroyPart3(any(), eq(event), 
eq(inTokenMode),
+        eq(duringRI), eq(invokeCallbacks), eq(expectedOldValue));
+  }
+
+  @Test
+  public void 
destroyWithEmptyRegionWithConcurrencyChecksAndNullVersionTagAddsATombstone() {
+    final TestableAbstractRegionMap arm = new TestableAbstractRegionMap(true);
+    final EntryEventImpl event = createEventForDestroy(arm._getOwner());
+    event.setOriginRemote(true);
+    final Object expectedOldValue = null;
+    final boolean inTokenMode = false;
+    final boolean duringRI = false;
+    assertThat(arm.destroy(event, inTokenMode, duringRI, false, false, 
expectedOldValue, false))
+        .isTrue();
+    assertThat(arm._getMap().containsKey(event.getKey())).isTrue();
+    boolean invokeCallbacks = true;
+    verify(arm._getOwner(), times(1)).basicDestroyPart2(any(), eq(event), 
eq(inTokenMode),
+        eq(false), eq(duringRI), eq(invokeCallbacks));
+    verify(arm._getOwner(), times(1)).basicDestroyPart3(any(), eq(event), 
eq(inTokenMode),
+        eq(duringRI), eq(invokeCallbacks), eq(expectedOldValue));
+    // instead of a TOMBSTONE we leave an entry whose value is REMOVE_PHASE1
+    // this looks like a bug. It is caused by some code in: 
AbstractRegionEntry.destroy()
+    // that calls removePhase1 when the versionTag is null.
+    // It seems like this code path needs to tell the higher levels
+    // to call removeEntry
+    RegionEntry re = (RegionEntry) arm._getMap().get(event.getKey());
+    assertThat(re.getValueAsToken()).isEqualTo(Token.REMOVED_PHASE1);
+  }
 
-    public LocalRegion owner;
+  private static class TestableAbstractRegionMap extends AbstractRegionMap {
 
     protected TestableAbstractRegionMap() {
+      this(false);
+    }
+
+    protected TestableAbstractRegionMap(boolean withConcurrencyChecks) {
+      this(withConcurrencyChecks, null, null);
+    }
+
+    protected TestableAbstractRegionMap(boolean withConcurrencyChecks,
+        CustomEntryConcurrentHashMap map, RegionEntryFactory factory) {
       super(null);
-      this.owner = mock(LocalRegion.class);
-      when(this.owner.getDataPolicy()).thenReturn(DataPolicy.REPLICATE);
-      
doThrow(EntryNotFoundException.class).when(this.owner).checkEntryNotFound(any());
+      LocalRegion owner = mock(LocalRegion.class);
+      CachePerfStats cachePerfStats = mock(CachePerfStats.class);
+      when(owner.getCachePerfStats()).thenReturn(cachePerfStats);
+      
when(owner.getConcurrencyChecksEnabled()).thenReturn(withConcurrencyChecks);
+      when(owner.getDataPolicy()).thenReturn(DataPolicy.REPLICATE);
+      
doThrow(EntryNotFoundException.class).when(owner).checkEntryNotFound(any());
       initialize(owner, new Attributes(), null, false);
+      if (map != null) {
+        this._setMap(map);
+      }
+      if (factory != null) {
+        this.setEntryFactory(factory);
+      }
     }
   }
 
-  private static class TxTestableAbstractRegionMap extends AbstractRegionMap {
+  private static class TestableVMLRURegionMap extends VMLRURegionMap {
+    private static EvictionAttributes evictionAttributes =
+        EvictionAttributes.createLRUEntryAttributes();
+
+    protected TestableVMLRURegionMap() {
+      this(false);
+    }
+
+    private static LocalRegion createOwner(boolean withConcurrencyChecks) {
+      LocalRegion owner = mock(LocalRegion.class);
+      CachePerfStats cachePerfStats = mock(CachePerfStats.class);
+      when(owner.getCachePerfStats()).thenReturn(cachePerfStats);
+      when(owner.getEvictionAttributes()).thenReturn(evictionAttributes);
+      
when(owner.getConcurrencyChecksEnabled()).thenReturn(withConcurrencyChecks);
+      when(owner.getDataPolicy()).thenReturn(DataPolicy.REPLICATE);
+      
doThrow(EntryNotFoundException.class).when(owner).checkEntryNotFound(any());
+      return owner;
+    }
+
+    private static EvictionController createEvictionController() {
+      EvictionController result = mock(EvictionController.class);
+      
when(result.getEvictionAlgorithm()).thenReturn(evictionAttributes.getAlgorithm());
+      EvictionCounters evictionCounters = mock(EvictionCounters.class);
+      when(result.getCounters()).thenReturn(evictionCounters);
+      return result;
+    }
 
-    public LocalRegion owner;
+    protected TestableVMLRURegionMap(boolean withConcurrencyChecks) {
+      super(createOwner(withConcurrencyChecks), new Attributes(), null, 
createEvictionController());
+    }
+
+    protected TestableVMLRURegionMap(boolean withConcurrencyChecks,
+        CustomEntryConcurrentHashMap hashMap) {
+      this(withConcurrencyChecks);
+      this._setMap(hashMap);
+    }
+  }
+
+  private static class TxTestableAbstractRegionMap extends AbstractRegionMap {
 
     protected TxTestableAbstractRegionMap() {
       super(null);
-      this.owner = mock(LocalRegion.class);
-      when(this.owner.getCache()).thenReturn(mock(InternalCache.class));
-      when(this.owner.isAllEvents()).thenReturn(true);
-      when(this.owner.isInitialized()).thenReturn(true);
+      LocalRegion owner = mock(LocalRegion.class);
+      when(owner.getCache()).thenReturn(mock(InternalCache.class));
+      when(owner.isAllEvents()).thenReturn(true);
+      when(owner.isInitialized()).thenReturn(true);
       initialize(owner, new Attributes(), null, false);
     }
   }
@@ -210,26 +789,25 @@ public class AbstractRegionMapTest {
   public void txApplyInvalidateDoesNotInvalidateRemovedToken() throws 
RegionClearedException {
     TxTestableAbstractRegionMap arm = new TxTestableAbstractRegionMap();
 
-    Object key = "key";
     Object newValue = "value";
-    arm.txApplyPut(Operation.CREATE, key, newValue, false,
+    arm.txApplyPut(Operation.CREATE, KEY, newValue, false,
         new TXId(mock(InternalDistributedMember.class), 1), 
mock(TXRmtEvent.class),
         mock(EventID.class), null, null, null, null, null, null, 1);
-    RegionEntry re = arm.getEntry(key);
+    RegionEntry re = arm.getEntry(KEY);
     assertNotNull(re);
 
     Token[] removedTokens =
         {Token.REMOVED_PHASE2, Token.REMOVED_PHASE1, Token.DESTROYED, 
Token.TOMBSTONE};
 
     for (Token token : removedTokens) {
-      verifyTxApplyInvalidate(arm, key, re, token);
+      verifyTxApplyInvalidate(arm, KEY, re, token);
     }
 
   }
 
   private void verifyTxApplyInvalidate(TxTestableAbstractRegionMap arm, Object 
key, RegionEntry re,
       Token token) throws RegionClearedException {
-    re.setValue(arm.owner, token);
+    re.setValue(arm._getOwner(), token);
     arm.txApplyInvalidate(key, Token.INVALID, false,
         new TXId(mock(InternalDistributedMember.class), 1), 
mock(TXRmtEvent.class), false,
         mock(EventID.class), null, null, null, null, null, null, 1);

-- 
To stop receiving notification emails like this one, please contact
dschnei...@apache.org.

Reply via email to