This is an automated email from the ASF dual-hosted git repository.
sai_boorlagadda 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 af07c3c GEODE-5223 Add unit tests for
AbstractRegionMap.txApplyDestroy (#1988)
af07c3c is described below
commit af07c3c674559ff562f902b58ad5e295282555b6
Author: Dale Emery <[email protected]>
AuthorDate: Fri Jun 1 10:26:19 2018 -0700
GEODE-5223 Add unit tests for AbstractRegionMap.txApplyDestroy (#1988)
---
.../geode/internal/cache/AbstractRegionMap.java | 66 +-
.../apache/geode/internal/cache/BucketRegion.java | 1 +
.../geode/internal/cache/InternalRegion.java | 3 +
.../geode/internal/cache/ProxyRegionMap.java | 6 +-
.../apache/geode/internal/cache/RegionEntry.java | 2 +-
.../cache/AbstractRegionMapTxApplyDestroyTest.java | 1480 ++++++++++++++++++++
6 files changed, 1522 insertions(+), 36 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 50b5371..ef4f2eb 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
@@ -922,7 +922,7 @@ public abstract class AbstractRegionMap
done = true;
} finally {
if (event != null) {
- event.release();
+ releaseEvent(event);
event = null;
}
}
@@ -974,7 +974,7 @@ public abstract class AbstractRegionMap
done = true;
} finally {
if (event != null) {
- event.release();
+ releaseEvent(event);
event = null;
}
}
@@ -998,7 +998,7 @@ public abstract class AbstractRegionMap
} // synchronized
} finally {
if (event != null)
- event.release();
+ releaseEvent(event);
OffHeapHelper.release(oldValue);
}
} catch (RegionClearedException rce) {
@@ -1048,7 +1048,7 @@ public abstract class AbstractRegionMap
final LocalRegion owner = _getOwner();
final boolean isRegionReady = !inTokenMode;
- final boolean hasRemoteOrigin = !((TXId)
txId).getMemberId().equals(owner.getMyId());
+ final boolean hasRemoteOrigin =
!txId.getMemberId().equals(owner.getMyId());
boolean callbackEventAddedToPending = false;
IndexManager oqlIndexManager = owner.getIndexManager();
try {
@@ -1068,9 +1068,8 @@ public abstract class AbstractRegionMap
// Create an entry event only if the calling context is
// a receipt of a TXCommitMessage AND there are callbacks
installed
// for this region
- boolean invokeCallbacks = shouldCreateCallbackEvent(owner,
isRegionReady || inRI);
@Released
- EntryEventImpl callbackEvent = createCallbackEvent(owner, op,
key, null, txId,
+ final EntryEventImpl callbackEvent = createCallbackEvent(owner,
op, key, null, txId,
txEvent, eventId, aCallbackArgument, filterRoutingInfo,
bridgeContext,
txEntryState, versionTag, tailKey);
try {
@@ -1099,7 +1098,7 @@ public abstract class AbstractRegionMap
} else {
if (!re.isTombstone()) {
{
- if (shouldPerformConcurrencyChecks(owner,
callbackEvent)
+ if (owner.getConcurrencyChecksEnabled()
&& callbackEvent.getVersionTag() != null) {
re.makeTombstone(owner,
callbackEvent.getVersionTag());
} else {
@@ -1119,6 +1118,7 @@ public abstract class AbstractRegionMap
}
owner.txApplyDestroyPart2(re, re.getKey(), inTokenMode,
clearOccured /* Clear Conflciting with the operation */);
+ boolean invokeCallbacks = shouldInvokeCallbacks(owner,
isRegionReady || inRI);
if (invokeCallbacks) {
switchEventOwnerAndOriginRemote(callbackEvent,
hasRemoteOrigin);
pendingCallbacks.add(callbackEvent);
@@ -1127,13 +1127,12 @@ public abstract class AbstractRegionMap
if (!clearOccured) {
lruEntryDestroy(re);
}
- if (owner.getConcurrencyChecksEnabled() && txEntryState != null
- && callbackEvent != null) {
+ if (owner.getConcurrencyChecksEnabled() && txEntryState !=
null) {
txEntryState.setVersionTag(callbackEvent.getVersionTag());
}
} finally {
if (!callbackEventAddedToPending)
- callbackEvent.release();
+ releaseEvent(callbackEvent);
}
}
}
@@ -1165,8 +1164,7 @@ public abstract class AbstractRegionMap
oldRe = putEntryIfAbsent(key, newRe);
} else {
try {
- boolean invokeCallbacks =
- shouldCreateCallbackEvent(owner, isRegionReady ||
inRI);
+ boolean invokeCallbacks = shouldInvokeCallbacks(owner,
isRegionReady || inRI);
callbackEvent = createCallbackEvent(owner, op, key, null,
txId, txEvent,
eventId, aCallbackArgument, filterRoutingInfo,
bridgeContext, txEntryState,
versionTag, tailKey);
@@ -1192,6 +1190,8 @@ public abstract class AbstractRegionMap
oldSize = owner.calculateRegionEntryValueSize(oldRe);
}
}
+ // TODO: Token.DESTROYED should only be used if
"inTokenMode".
+ // Otherwise this should be a TOMBSTONE
oldRe.setValue(owner, Token.DESTROYED);
EntryLogger.logTXDestroy(_getOwnerObject(), key);
if (wasTombstone) {
@@ -1203,13 +1203,13 @@ public abstract class AbstractRegionMap
lruEntryDestroy(oldRe);
} finally {
if (!callbackEventAddedToPending)
- callbackEvent.release();
+ releaseEvent(callbackEvent);
}
} catch (RegionClearedException rce) {
owner.txApplyDestroyPart2(oldRe, oldRe.getKey(),
inTokenMode,
true /* Clear Conflicting with the operation */);
}
- if (shouldPerformConcurrencyChecks(owner, callbackEvent)
+ if (owner.getConcurrencyChecksEnabled()
&& callbackEvent.getVersionTag() != null) {
oldRe.makeTombstone(owner, callbackEvent.getVersionTag());
} else if (!inTokenMode) {
@@ -1225,7 +1225,7 @@ public abstract class AbstractRegionMap
if (!opCompleted) {
// already has value set to Token.DESTROYED
opCompleted = true;
- boolean invokeCallbacks = shouldCreateCallbackEvent(owner,
isRegionReady || inRI);
+ boolean invokeCallbacks = shouldInvokeCallbacks(owner,
isRegionReady || inRI);
callbackEvent = createCallbackEvent(owner, op, key, null, txId,
txEvent, eventId,
aCallbackArgument, filterRoutingInfo, bridgeContext,
txEntryState, versionTag,
tailKey);
@@ -1246,8 +1246,7 @@ public abstract class AbstractRegionMap
}
EntryLogger.logTXDestroy(_getOwnerObject(), key);
owner.updateSizeOnCreate(newRe.getKey(), 0);
- if (shouldPerformConcurrencyChecks(owner, callbackEvent)
- && callbackEvent.getVersionTag() != null) {
+ if (owner.getConcurrencyChecksEnabled() &&
callbackEvent.getVersionTag() != null) {
newRe.makeTombstone(owner, callbackEvent.getVersionTag());
} else if (!inTokenMode) {
// only remove for NORMAL regions if they do not generate
versions see 51781
@@ -1261,11 +1260,10 @@ public abstract class AbstractRegionMap
// and will be removed when gii completes
} finally {
if (!callbackEventAddedToPending)
- callbackEvent.release();
+ releaseEvent(callbackEvent);
}
}
- if (owner.getConcurrencyChecksEnabled() && txEntryState != null
- && callbackEvent != null) {
+ if (owner.getConcurrencyChecksEnabled() && txEntryState != null) {
txEntryState.setVersionTag(callbackEvent.getVersionTag());
}
}
@@ -1276,7 +1274,7 @@ public abstract class AbstractRegionMap
oqlIndexManager.countDownIndexUpdaters();
}
}
- } else if (re == null) {
+ } else { // re == null
// Fix bug#43594
// In cases where bucket region is re-created, it may so happen that
// the destroy is already applied on the Initial image provider, thus
@@ -1295,7 +1293,7 @@ public abstract class AbstractRegionMap
callbackEventAddedToPending = true;
} finally {
if (!callbackEventAddedToPending)
- callbackEvent.release();
+ releaseEvent(callbackEvent);
}
}
} catch (DiskAccessException dae) {
@@ -1304,6 +1302,10 @@ public abstract class AbstractRegionMap
}
}
+ void releaseEvent(final EntryEventImpl event) {
+ event.release();
+ }
+
/**
* If true then invalidates that throw EntryNotFoundException or that are
already invalid will
* first call afterInvalidate on CacheListeners. The old value on the event
passed to
@@ -1860,7 +1862,7 @@ public abstract class AbstractRegionMap
// a receipt of a TXCommitMessage AND there are callbacks
// installed
// for this region
- boolean invokeCallbacks = shouldCreateCallbackEvent(owner,
owner.isInitialized());
+ boolean invokeCallbacks = shouldInvokeCallbacks(owner,
owner.isInitialized());
boolean callbackEventInPending = false;
callbackEvent = createCallbackEvent(owner,
localOp ? Operation.LOCAL_INVALIDATE :
Operation.INVALIDATE, key, newValue,
@@ -1910,13 +1912,13 @@ public abstract class AbstractRegionMap
}
} finally {
if (!callbackEventInPending)
- callbackEvent.release();
+ releaseEvent(callbackEvent);
}
}
}
}
if (!opCompleted) {
- boolean invokeCallbacks = shouldCreateCallbackEvent(owner,
owner.isInitialized());
+ boolean invokeCallbacks = shouldInvokeCallbacks(owner,
owner.isInitialized());
boolean callbackEventInPending = false;
callbackEvent = createCallbackEvent(owner,
localOp ? Operation.LOCAL_INVALIDATE : Operation.INVALIDATE,
key, newValue, txId,
@@ -1953,7 +1955,7 @@ public abstract class AbstractRegionMap
}
} finally {
if (!callbackEventInPending)
- callbackEvent.release();
+ releaseEvent(callbackEvent);
}
}
} finally {
@@ -1974,7 +1976,7 @@ public abstract class AbstractRegionMap
// a receipt of a TXCommitMessage AND there are callbacks
// installed
// for this region
- boolean invokeCallbacks = shouldCreateCallbackEvent(owner,
owner.isInitialized());
+ boolean invokeCallbacks = shouldInvokeCallbacks(owner,
owner.isInitialized());
boolean callbackEventInPending = false;
callbackEvent = createCallbackEvent(owner,
localOp ? Operation.LOCAL_INVALIDATE : Operation.INVALIDATE,
key, newValue, txId,
@@ -2015,7 +2017,7 @@ public abstract class AbstractRegionMap
}
} finally {
if (!callbackEventInPending)
- callbackEvent.release();
+ releaseEvent(callbackEvent);
}
return;
}
@@ -2038,7 +2040,7 @@ public abstract class AbstractRegionMap
callbackEventInPending = true;
} finally {
if (!callbackEventInPending)
- callbackEvent.release();
+ releaseEvent(callbackEvent);
}
}
}
@@ -2126,7 +2128,7 @@ public abstract class AbstractRegionMap
private void txHandleWANEvent(final LocalRegion owner, EntryEventImpl
callbackEvent,
TXEntryState txEntryState) {
- ((BucketRegion) owner).handleWANEvent(callbackEvent);
+ owner.handleWANEvent(callbackEvent);
if (txEntryState != null) {
txEntryState.setTailKey(callbackEvent.getTailKey());
}
@@ -2219,7 +2221,7 @@ public abstract class AbstractRegionMap
}
}
- static boolean shouldCreateCallbackEvent(final LocalRegion owner, final
boolean isInitialized) {
+ static boolean shouldInvokeCallbacks(final LocalRegion owner, final boolean
isInitialized) {
LocalRegion lr = owner;
boolean isPartitioned = lr.isUsedForPartitionedRegionBucket();
@@ -2253,7 +2255,7 @@ public abstract class AbstractRegionMap
DistributedMember originator = null;
// txId should not be null even on localOrigin
Assert.assertTrue(txId != null);
- originator = ((TXId) txId).getMemberId();
+ originator = txId.getMemberId();
InternalRegion eventRegion = internalRegion;
if (eventRegion.isUsedForPartitionedRegionBucket()) {
diff --git
a/geode-core/src/main/java/org/apache/geode/internal/cache/BucketRegion.java
b/geode-core/src/main/java/org/apache/geode/internal/cache/BucketRegion.java
index 07dc319..0fb745d 100644
--- a/geode-core/src/main/java/org/apache/geode/internal/cache/BucketRegion.java
+++ b/geode-core/src/main/java/org/apache/geode/internal/cache/BucketRegion.java
@@ -569,6 +569,7 @@ public class BucketRegion extends DistributedRegion
implements Bucket {
return eventSeqNum.get();
}
+ @Override
public void handleWANEvent(EntryEventImpl event) {
if (this.eventSeqNum == null) {
if (logger.isDebugEnabled()) {
diff --git
a/geode-core/src/main/java/org/apache/geode/internal/cache/InternalRegion.java
b/geode-core/src/main/java/org/apache/geode/internal/cache/InternalRegion.java
index 38d517f..8b887ef 100644
---
a/geode-core/src/main/java/org/apache/geode/internal/cache/InternalRegion.java
+++
b/geode-core/src/main/java/org/apache/geode/internal/cache/InternalRegion.java
@@ -405,4 +405,7 @@ public interface InternalRegion extends Region,
HasCachePerfStats, RegionEntryCo
}
EvictionController getEvictionController();
+
+ default void handleWANEvent(EntryEventImpl event) {}
+
}
diff --git
a/geode-core/src/main/java/org/apache/geode/internal/cache/ProxyRegionMap.java
b/geode-core/src/main/java/org/apache/geode/internal/cache/ProxyRegionMap.java
index 26d95a6..6eb4479 100644
---
a/geode-core/src/main/java/org/apache/geode/internal/cache/ProxyRegionMap.java
+++
b/geode-core/src/main/java/org/apache/geode/internal/cache/ProxyRegionMap.java
@@ -271,7 +271,7 @@ class ProxyRegionMap implements RegionMap {
if (event != null) {
event.addDestroy(this.owner, markerEntry, key, aCallbackArgument);
}
- if (AbstractRegionMap.shouldCreateCallbackEvent(this.owner,
!inTokenMode)) {
+ if (AbstractRegionMap.shouldInvokeCallbacks(this.owner, !inTokenMode)) {
// fix for bug 39526
@Released
EntryEventImpl e = AbstractRegionMap.createCallbackEvent(this.owner,
op, key, null,
@@ -294,7 +294,7 @@ class ProxyRegionMap implements RegionMap {
if (event != null) {
event.addInvalidate(this.owner, markerEntry, key, newValue,
aCallbackArgument);
}
- if (AbstractRegionMap.shouldCreateCallbackEvent(this.owner,
this.owner.isInitialized())) {
+ if (AbstractRegionMap.shouldInvokeCallbacks(this.owner,
this.owner.isInitialized())) {
// fix for bug 39526
@Released
EntryEventImpl e = AbstractRegionMap.createCallbackEvent(this.owner,
@@ -320,7 +320,7 @@ class ProxyRegionMap implements RegionMap {
if (event != null) {
event.addPut(putOperation, this.owner, markerEntry, key, newValue,
aCallbackArgument);
}
- if (AbstractRegionMap.shouldCreateCallbackEvent(this.owner,
this.owner.isInitialized())) {
+ if (AbstractRegionMap.shouldInvokeCallbacks(this.owner,
this.owner.isInitialized())) {
// fix for bug 39526
@Released
EntryEventImpl e = AbstractRegionMap.createCallbackEvent(this.owner,
putOperation, key,
diff --git
a/geode-core/src/main/java/org/apache/geode/internal/cache/RegionEntry.java
b/geode-core/src/main/java/org/apache/geode/internal/cache/RegionEntry.java
index 24cb359..c3ab74c 100644
--- a/geode-core/src/main/java/org/apache/geode/internal/cache/RegionEntry.java
+++ b/geode-core/src/main/java/org/apache/geode/internal/cache/RegionEntry.java
@@ -146,7 +146,7 @@ public interface RegionEntry {
/**
* Returns true if this entry does not exist. This is true if removal has
started (value ==
- * Token.REMOVED_PHASE1) or has completed (value == Token.REMOVED_PHASE2).
+ * Token.REMOVED_PHASE1) or has completed (value == Token.REMOVED_PHASE2) or
is a TOMBSTONE.
*/
boolean isRemoved();
diff --git
a/geode-core/src/test/java/org/apache/geode/internal/cache/AbstractRegionMapTxApplyDestroyTest.java
b/geode-core/src/test/java/org/apache/geode/internal/cache/AbstractRegionMapTxApplyDestroyTest.java
new file mode 100644
index 0000000..0517591
--- /dev/null
+++
b/geode-core/src/test/java/org/apache/geode/internal/cache/AbstractRegionMapTxApplyDestroyTest.java
@@ -0,0 +1,1480 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
contributor license
+ * agreements. See the NOTICE file distributed with this work for additional
information regarding
+ * copyright ownership. The ASF licenses this file to You under the Apache
License; private Version
+ * 2.0 (the
+ * "License"); you may not use this file except in compliance with the
License. You may obtain a
+ * copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing; private software
distributed under the
+ * License
+ * is distributed on an "AS IS" BASIS; private WITHOUT WARRANTIES OR
CONDITIONS OF ANY KIND; private
+ * either express
+ * or implied. See the License for the specific language governing permissions
and limitations under
+ * the License.
+ */
+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.assertj.core.api.SoftAssertions.assertSoftly;
+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.inOrder;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.same;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+import static org.mockito.MockitoAnnotations.initMocks;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+import org.mockito.InOrder;
+import org.mockito.Mock;
+
+import org.apache.geode.cache.DiskAccessException;
+import org.apache.geode.cache.Operation;
+import org.apache.geode.cache.query.internal.index.IndexManager;
+import org.apache.geode.cache.query.internal.index.IndexProtocol;
+import
org.apache.geode.distributed.internal.membership.InternalDistributedMember;
+import org.apache.geode.internal.cache.TXEntryState.DistTxThinEntryState;
+import org.apache.geode.internal.cache.tier.sockets.ClientProxyMembershipID;
+import org.apache.geode.internal.cache.versions.VersionStamp;
+import org.apache.geode.internal.cache.versions.VersionTag;
+import
org.apache.geode.internal.util.concurrent.ConcurrentMapWithReusableEntries;
+import org.apache.geode.test.junit.categories.UnitTest;
+
+@SuppressWarnings("unchecked")
+@Category(UnitTest.class)
+public class AbstractRegionMapTxApplyDestroyTest {
+ // parameters
+ private Object key = "key";
+ @Mock
+ private TXId txId;
+ private TXRmtEvent txEvent;
+ private boolean inTokenMode;
+ private boolean inRI;
+ private Operation operation = Operation.DESTROY;
+ @Mock
+ private EventID eventId;
+ private Object aCallbackArgument = "aCallbackArgument";
+ private final List<EntryEventImpl> pendingCallbacks = new ArrayList<>();
+ private FilterRoutingInfo filterRoutingInfo = null; // Provide a meaningful
value for this?
+ @Mock
+ private ClientProxyMembershipID bridgeContext;
+ private boolean isOriginRemote = false;
+ @Mock
+ private TXEntryState txEntryState;
+ private VersionTag versionTag;
+ private long tailKey = 223L;
+
+ @Mock
+ private InternalDistributedMember myId;
+ @Mock
+ private InternalDistributedMember remoteId;
+ @Mock
+ private KeyInfo keyInfo;
+ @Mock
+ private ConcurrentMapWithReusableEntries entryMap;
+ @Mock
+ private RegionEntryFactory regionEntryFactory;
+ @Mock
+ private RegionEntry existingRegionEntry;
+ @Mock
+ private RegionEntry factoryRegionEntry;
+ @Mock
+ private RegionEntry oldRegionEntry;
+ @Mock
+ private PartitionedRegion partitionedRegion;
+ @Mock
+ private VersionTag existingVersionTag;
+ @Mock
+ private CachePerfStats cachePerfStats;
+
+ private LocalRegion owner;
+ private TestableAbstractRegionMap regionMap;
+
+ @Before
+ public void setup() {
+ initMocks(this);
+ VersionStamp versionStamp = mock(VersionStamp.class);
+ when(versionStamp.asVersionTag()).thenReturn(existingVersionTag);
+ when(existingRegionEntry.getVersionStamp()).thenReturn(versionStamp);
+ when(existingRegionEntry.getKey()).thenReturn(key);
+ when(factoryRegionEntry.getKey()).thenReturn(key);
+ when(oldRegionEntry.getKey()).thenReturn(key);
+ when(keyInfo.getKey()).thenReturn(key);
+ when(txId.getMemberId()).thenReturn(myId);
+ }
+
+ // tests for no region entry.
+ // Each of these tests requires givenNotInTokenMode and
givenNoConcurrencyChecks
+
+ @Test
+ public void
txApplyDestroySetCorrectPendingCallback_givenNoRegionEntryNotInTokenModeNoConcurrencyChecks()
{
+ givenLocalRegion();
+ givenNoRegionEntry();
+ givenNotInTokenMode();
+ givenNoConcurrencyChecks();
+ when(owner.generateEventID()).thenReturn(true);
+ when(keyInfo.getCallbackArg()).thenReturn(aCallbackArgument);
+
+ doTxApplyDestroy();
+ assertThat(pendingCallbacks).hasSize(1);
+ EntryEventImpl callbackEvent = pendingCallbacks.get(0);
+
+ // noinspection Duplicates
+ assertSoftly(softly -> {
+ softly.assertThat(callbackEvent.getRegion()).isSameAs(owner);
+ softly.assertThat(callbackEvent.getOperation()).isSameAs(operation);
+ softly.assertThat(callbackEvent.getKey()).isSameAs(key);
+ softly.assertThat(callbackEvent.getNewValue()).isNull();
+ softly.assertThat(callbackEvent.getTransactionId()).isSameAs(txId);
+ softly.assertThat(callbackEvent.getEventId()).isSameAs(eventId);
+
softly.assertThat(callbackEvent.getCallbackArgument()).isSameAs(aCallbackArgument);
+
softly.assertThat(callbackEvent.getLocalFilterInfo()).isSameAs(filterRoutingInfo);
+ softly.assertThat(callbackEvent.getContext()).isSameAs(bridgeContext);
+
softly.assertThat(callbackEvent.isOriginRemote()).isEqualTo(isOriginRemote);
+ softly.assertThat(callbackEvent.getVersionTag()).isEqualTo(versionTag);
+ softly.assertThat(callbackEvent.getTailKey()).isEqualTo(tailKey);
+ });
+ }
+
+ @Test
+ public void
addsCallbackEvent_givenNoRegionEntryNotInTokenModeNoConcurrencyChecks_andBucket()
{
+ givenBucketRegion();
+ givenNoRegionEntry();
+ givenNotInTokenMode();
+ givenNoConcurrencyChecks();
+
+ when(partitionedRegion.generateEventID()).thenReturn(true);
+ when(keyInfo.getCallbackArg()).thenReturn(aCallbackArgument);
+
+ doTxApplyDestroy();
+
+ verify(owner, times(1)).handleWANEvent(any());
+ verify(txEntryState, times(1)).setTailKey(tailKey);
+
+ assertThat(pendingCallbacks).hasSize(1);
+ EntryEventImpl callbackEvent = pendingCallbacks.get(0);
+
+ // noinspection Duplicates
+ assertSoftly(softly -> {
+ softly.assertThat(callbackEvent.getRegion()).isSameAs(partitionedRegion);
+ softly.assertThat(callbackEvent.getOperation()).isSameAs(operation);
+ softly.assertThat(callbackEvent.getKey()).isSameAs(key);
+ softly.assertThat(callbackEvent.getNewValue()).isNull();
+ softly.assertThat(callbackEvent.getTransactionId()).isSameAs(txId);
+ softly.assertThat(callbackEvent.getEventId()).isSameAs(eventId);
+
softly.assertThat(callbackEvent.getCallbackArgument()).isSameAs(aCallbackArgument);
+
softly.assertThat(callbackEvent.getLocalFilterInfo()).isSameAs(filterRoutingInfo);
+ softly.assertThat(callbackEvent.getContext()).isSameAs(bridgeContext);
+
softly.assertThat(callbackEvent.isOriginRemote()).isEqualTo(isOriginRemote);
+ softly.assertThat(callbackEvent.getVersionTag()).isEqualTo(versionTag);
+ softly.assertThat(callbackEvent.getTailKey()).isEqualTo(tailKey);
+ });
+ }
+
+ @Test
+ public void
txApplyDestroyCallReleaseEvent_givenNoRegionEntryNotInTokenModeNoConcurrencyChecksAndBucket_whenHandleWANEventThrows()
{
+ givenBucketRegion();
+ givenNoRegionEntry();
+ givenNotInTokenMode();
+ givenNoConcurrencyChecks();
+ doThrow(RuntimeException.class).when(owner).handleWANEvent(any());
+
+
assertThatThrownBy(this::doTxApplyDestroy).isInstanceOf(RuntimeException.class);
+
+ verify(regionMap, times(1)).releaseEvent(any());
+ }
+
+ // tests for "existingRegionEntry"
+
+ @Test
+ public void
txApplyDestroyHasNoPendingCallback_givenExistingRegionEntryThatIsRemoved() {
+ givenLocalRegion();
+ givenExistingRegionEntry();
+ when(existingRegionEntry.isRemoved()).thenReturn(true);
+
+ doTxApplyDestroy();
+
+ assertThat(pendingCallbacks).isEmpty();
+ }
+
+ @Test
+ public void
txApplyDestroyInvokesRescheduleTombstone_givenExistingRegionEntryThatIsTombstone()
{
+ givenLocalRegion();
+ givenExistingRegionEntry();
+ when(existingRegionEntry.isRemoved()).thenReturn(true);
+ when(existingRegionEntry.isTombstone()).thenReturn(true);
+
+ doTxApplyDestroy();
+
+ verify(owner, times(1)).rescheduleTombstone(same(existingRegionEntry),
any());
+ }
+
+ @Test
+ public void doesNotAddCallbackEvent_ifExistingRegionEntryIsTombstone()
throws Exception {
+ givenLocalRegion();
+ givenExistingRegionEntry();
+ when(existingRegionEntry.isRemoved()).thenReturn(true);
+ when(existingRegionEntry.isTombstone()).thenReturn(true);
+
+ doTxApplyDestroy();
+
+ assertThat(pendingCallbacks).isEmpty();
+ verify(existingRegionEntry, never()).makeTombstone(any(), any());
+ verify(txEntryState, never()).setVersionTag(any());
+ }
+
+ @Test
+ public void
txApplyDestroyHasNoPendingCallback_givenExistingRegionEntryWithInTokenModeAndNotInRI()
{
+ givenLocalRegion();
+ givenConcurrencyChecks();
+ givenExistingRegionEntry();
+ this.inTokenMode = true;
+ this.inRI = false;
+
+ doTxApplyDestroy();
+
+ assertThat(pendingCallbacks).isEmpty();
+ verify(owner, times(1)).txApplyDestroyPart2(same(existingRegionEntry),
eq(key),
+ eq(this.inTokenMode), eq(false));
+ }
+
+ @Test
+ public void
doesNotAddCallbackEvent_givenExistingRegionEntryWithInTokenModeAndNotInRI()
+ throws Exception {
+ givenLocalRegion();
+ givenConcurrencyChecks();
+ givenExistingRegionEntry();
+ this.inTokenMode = true;
+ this.inRI = false;
+
+ doTxApplyDestroy();
+
+ assertThat(pendingCallbacks).isEmpty();
+ verify(owner).generateAndSetVersionTag(any(EntryEventImpl.class),
same(existingRegionEntry));
+ verify(existingRegionEntry, never()).makeTombstone(any(), any());
+ verify(txEntryState).setVersionTag(any());
+ }
+
+ @Test
+ public void setsRegionEntryOnEvent_ifExistingRegionEntryIsValid() throws
Exception {
+ givenLocalRegion();
+ givenConcurrencyChecks();
+ givenExistingRegionEntry();
+
+ Object oldValue = "oldValue";
+ when(existingRegionEntry.getValueInVM(owner)).thenReturn(oldValue);
+
+ doTxApplyDestroy();
+
+ assertThat(pendingCallbacks).size().isEqualTo(1);
+ EntryEventImpl event = pendingCallbacks.get(0);
+ assertThat(event.getRegionEntry()).isSameAs(existingRegionEntry);
+ assertThat(event.getOldValue()).isSameAs(oldValue);
+
+ verify(owner).generateAndSetVersionTag(any(EntryEventImpl.class),
same(existingRegionEntry));
+ verify(existingRegionEntry, never()).makeTombstone(any(), any());
+ verify(txEntryState).setVersionTag(event.getVersionTag());
+ }
+
+ @Test
+ public void
txApplyDestroyUpdateIndexes_givenExistingRegionEntryThatIsValid() throws
Exception {
+ givenLocalRegion();
+ givenConcurrencyChecks();
+ givenExistingRegionEntry();
+ IndexManager indexManager = mock(IndexManager.class);
+ when(owner.getIndexManager()).thenReturn(indexManager);
+
+ doTxApplyDestroy();
+
+ verify(indexManager, times(1)).updateIndexes(same(existingRegionEntry),
+ eq(IndexManager.REMOVE_ENTRY), eq(IndexProtocol.OTHER_OP));
+ }
+
+ @Test
+ public void
txApplyDestroyCallsAddDestroy_givenExistingRegionEntryThatIsValidAndTxRmtEvent()
{
+ givenLocalRegion();
+ givenConcurrencyChecks();
+ givenExistingRegionEntry();
+ txEvent = mock(TXRmtEvent.class);
+
+ doTxApplyDestroy();
+
+ verify(txEvent, times(1)).addDestroy(same(owner),
same(existingRegionEntry), eq(key),
+ same(aCallbackArgument));
+ }
+
+ @Test
+ public void
callsProcessAndGenerateTXVersionTag_givenExistingRegionEntryThatIsValid() {
+ givenLocalRegion();
+ givenConcurrencyChecks();
+ givenExistingRegionEntry();
+
+ doTxApplyDestroy();
+
+ EntryEventImpl callbackEvent = pendingCallbacks.get(0);
+ verify(regionMap,
times(1)).processAndGenerateTXVersionTag(same(callbackEvent),
+ same(existingRegionEntry), same(txEntryState));
+ assertThat(callbackEvent.getNextRegionVersion()).isEqualTo(-1L); //
Default value
+ }
+
+ @Test
+ public void
setsEventNextRegionVersionOnCallbackEvent_givenExistingRegionEntryThatIsValidAndDistTxEntryStateExists()
{
+ givenLocalRegion();
+ givenConcurrencyChecks();
+ givenExistingRegionEntry();
+
+ DistTxThinEntryState distTxEntryStates = mock(DistTxThinEntryState.class);
+ when(txEntryState.getDistTxEntryStates()).thenReturn(distTxEntryStates);
+ when(distTxEntryStates.getRegionVersion()).thenReturn(999L);
+
+ doTxApplyDestroy();
+
+ EntryEventImpl callbackEvent = pendingCallbacks.get(0);
+ assertThat(callbackEvent.getNextRegionVersion()).isEqualTo(999L); //
Default value
+ }
+
+ @Test
+ public void
txApplyDestroySetsValueToDestroyToken_givenExistingRegionEntryThatIsValidWithInTokenMode()
+ throws Exception {
+ givenLocalRegion();
+ givenConcurrencyChecks();
+ givenExistingRegionEntry();
+ inTokenMode = true;
+
+ doTxApplyDestroy();
+
+ verify(existingRegionEntry, times(1)).setValue(same(owner),
eq(Token.DESTROYED));
+ }
+
+ @Test
+ public void
txApplyDestroyHandlesClear_givenExistingRegionEntryThatIsValidWithInTokenModeAndSetValueThrowsRegionClearedException()
+ throws Exception {
+ givenLocalRegion();
+ givenConcurrencyChecks();
+ givenExistingRegionEntry();
+ inTokenMode = true;
+
doThrow(RegionClearedException.class).when(existingRegionEntry).setValue(same(owner),
+ eq(Token.DESTROYED));
+
+ doTxApplyDestroy();
+
+ verify(owner, times(1)).txApplyDestroyPart2(any(), any(), anyBoolean(),
eq(true));
+ verify(regionMap, never()).lruEntryDestroy(any());
+ }
+
+ @Test
+ public void
txApplyDestroyHandlesNoClear_givenExistingRegionEntryThatIsValidWithInTokenMode()
{
+ givenLocalRegion();
+ givenConcurrencyChecks();
+ givenExistingRegionEntry();
+ inTokenMode = true;
+
+ doTxApplyDestroy();
+
+ verify(owner, times(1)).txApplyDestroyPart2(any(), any(), anyBoolean(),
eq(false));
+ verify(regionMap, times(1)).lruEntryDestroy(any());
+ }
+
+ @Test
+ public void
txApplyDestroyCallsUnscheduleTombstone_givenExistingRegionEntryThatIsTombstoneWithInTokenMode()
{
+ givenLocalRegion();
+ givenConcurrencyChecks();
+ givenExistingRegionEntry();
+ inTokenMode = true;
+ when(existingRegionEntry.getValueInVM(owner)).thenReturn(Token.TOMBSTONE);
+
+ doTxApplyDestroy();
+
+ verify(owner, times(1)).unscheduleTombstone(same(existingRegionEntry));
+ }
+
+ @Test
+ public void
txApplyDestroyCallsRemoveEntry_givenExistingRegionEntryThatIsValidWithoutInTokenModeWithoutConcurrencyCheck()
+ throws Exception {
+ givenLocalRegion();
+ givenNoConcurrencyChecks();
+ givenExistingRegionEntry();
+ inTokenMode = false;
+
+ doTxApplyDestroy();
+
+ verify(existingRegionEntry, times(1)).removePhase1(same(owner), eq(false));
+ verify(existingRegionEntry, times(1)).removePhase2();
+ verify(regionMap, times(1)).removeEntry(eq(key),
same(existingRegionEntry), eq(false));
+ }
+
+ @Test
+ public void
txApplyDestroyCallsRescheduleTombstone_givenExistingRegionEntryThatIsValidWithoutInTokenModeWithConcurrencyCheckButNoVersionTag()
+ throws Exception {
+ givenLocalRegion();
+ givenConcurrencyChecks();
+ givenExistingRegionEntry();
+ inTokenMode = false;
+ versionTag = null;
+
+ doTxApplyDestroy();
+
+ verify(existingRegionEntry, times(1)).removePhase1(same(owner), eq(false));
+ verify(existingRegionEntry, times(1)).removePhase2();
+ verify(regionMap, times(1)).removeEntry(eq(key),
same(existingRegionEntry), eq(false));
+ }
+
+ @Test
+ public void
txApplyDestroyCallsMakeTombstone_givenExistingRegionEntryThatIsValidWithoutInTokenModeWithConcurrencyCheckAndVersionTag()
+ throws Exception {
+ givenLocalRegion();
+ givenConcurrencyChecks();
+ givenExistingRegionEntry();
+ inTokenMode = false;
+ versionTag = mock(VersionTag.class);
+
+ doTxApplyDestroy();
+
+ verify(existingRegionEntry, times(1)).makeTombstone(same(owner),
same(versionTag));
+ }
+
+ @Test
+ public void
txApplyDestroyCallsUpdateSizeOnRemove_givenExistingRegionEntryThatIsValid() {
+ givenLocalRegion();
+ givenConcurrencyChecks();
+ givenExistingRegionEntry();
+ int oldSize = 79;
+
when(owner.calculateRegionEntryValueSize(same(existingRegionEntry))).thenReturn(oldSize);
+
+ doTxApplyDestroy();
+
+ verify(owner, times(1)).updateSizeOnRemove(eq(key), eq(oldSize));
+ }
+
+ @Test
+ public void txApplyDestroyCallsReleaseEvent_givenExistingRegionEntry() {
+ givenLocalRegion();
+ givenExistingRegionEntry();
+
+ doTxApplyDestroy();
+
+ verify(regionMap, times(1)).releaseEvent(any());
+ }
+
+ @Test
+ public void
txApplyDestroyHasPendingCallback_givenExistingRegionEntryWithoutInTokenModeAndNotInRI()
{
+ givenLocalRegion();
+ givenConcurrencyChecks();
+ givenExistingRegionEntry();
+ inTokenMode = false;
+ inRI = false;
+
+ doTxApplyDestroy();
+
+ assertThat(pendingCallbacks).hasSize(1);
+ verify(owner, times(1)).txApplyDestroyPart2(same(existingRegionEntry),
eq(key), eq(inTokenMode),
+ eq(false));
+
+ }
+
+ @Test
+ public void
txApplyDestroyHasPendingCallback_givenExistingRegionEntryWithoutInTokenModeAndWithInRI()
{
+ givenLocalRegion();
+ givenConcurrencyChecks();
+ givenExistingRegionEntry();
+ inTokenMode = false;
+ inRI = true;
+
+ doTxApplyDestroy();
+
+ assertThat(pendingCallbacks).hasSize(1);
+ verify(owner, times(1)).txApplyDestroyPart2(same(existingRegionEntry),
eq(key), eq(inTokenMode),
+ eq(false));
+ }
+
+ @Test
+ public void
txApplyDestroyHasPendingCallback_givenExistingRegionEntryWithInTokenModeAndInRI()
{
+ givenLocalRegion();
+ givenConcurrencyChecks();
+ givenExistingRegionEntry();
+ inTokenMode = true;
+ inRI = true;
+
+ doTxApplyDestroy();
+
+ assertThat(pendingCallbacks).hasSize(1);
+ verify(owner, times(1)).txApplyDestroyPart2(same(existingRegionEntry),
eq(key), eq(inTokenMode),
+ eq(false));
+ }
+
+ @Test
+ public void
txApplyDestroyHasNoPendingCallback_givenExistingRegionEntryWithPartitionedRegion()
{
+ givenBucketRegion();
+ givenExistingRegionEntry();
+
+ doTxApplyDestroy();
+
+ assertThat(pendingCallbacks).isEmpty();
+ verify(owner, times(1)).txApplyDestroyPart2(same(existingRegionEntry),
eq(key), eq(inTokenMode),
+ eq(false));
+ }
+
+ @Test
+ public void
txApplyDestroyCallsHandleWanEvent_givenExistingRegionEntryWithPartitionedRegion()
{
+ givenBucketRegion();
+ givenExistingRegionEntry();
+
+ doTxApplyDestroy();
+
+ verify(owner, times(1)).handleWANEvent(any());
+ verify(txEntryState, times(1)).setTailKey(tailKey);
+ }
+
+ @Test
+ public void
txApplyDestroyDoesNotCallSetVersionTag_givenExistingRegionEntryWithPartitionedRegionButNoConcurrencyChecks()
{
+ givenBucketRegion();
+ givenExistingRegionEntry();
+ versionTag = mock(VersionTag.class);
+ givenNoConcurrencyChecks();
+
+ doTxApplyDestroy();
+
+ verify(txEntryState, never()).setVersionTag(any());
+ }
+
+ @Test
+ public void
txApplyDestroyPreparesAndReleasesIndexManager_givenExistingRegionEntryWithIndexManager()
{
+ givenLocalRegion();
+ givenExistingRegionEntry();
+ IndexManager indexManager = mock(IndexManager.class);
+ when(owner.getIndexManager()).thenReturn(indexManager);
+
+ doTxApplyDestroy();
+
+ InOrder inOrder = inOrder(indexManager);
+ inOrder.verify(indexManager, times(1)).waitForIndexInit();
+ inOrder.verify(indexManager, times(1)).countDownIndexUpdaters();
+ }
+
+ @Test
+ public void
txApplyDestroyCallsSetVersionTag_givenExistingRegionEntryWithPartitionedRegionAndConcurrencyChecks()
{
+ givenBucketRegion();
+ givenExistingRegionEntry();
+ versionTag = mock(VersionTag.class);
+ givenConcurrencyChecks();
+
+ doTxApplyDestroy();
+
+ verify(txEntryState, times(1)).setVersionTag(same(versionTag));
+ }
+
+ @Test
+ public void
txApplyDestroyHasNoPendingCallback_givenExistingRegionEntryWithoutConcurrencyChecks()
{
+ givenLocalRegion();
+ givenExistingRegionEntry();
+ givenNoConcurrencyChecks();
+
+ doTxApplyDestroy();
+
+ assertThat(pendingCallbacks).isEmpty();
+ verify(owner, times(1)).txApplyDestroyPart2(same(existingRegionEntry),
eq(key), eq(inTokenMode),
+ eq(false));
+ }
+
+ @Test
+ public void
txApplyDestroyHasPendingCallback_givenExistingRegionEntryWithShouldDispatchListenerEvent()
{
+ givenLocalRegion();
+ givenExistingRegionEntry();
+ when(owner.shouldDispatchListenerEvent()).thenReturn(true);
+
+ doTxApplyDestroy();
+
+ assertThat(pendingCallbacks).hasSize(1);
+ verify(owner, times(1)).txApplyDestroyPart2(same(existingRegionEntry),
eq(key), eq(inTokenMode),
+ eq(false));
+ }
+
+ @Test
+ public void
txApplyDestroyHasPendingCallback_givenExistingRegionEntryWithshouldNotifyBridgeClients()
{
+ givenLocalRegion();
+ givenExistingRegionEntry();
+ when(owner.shouldNotifyBridgeClients()).thenReturn(true);
+
+ doTxApplyDestroy();
+
+ assertThat(pendingCallbacks).hasSize(1);
+ verify(owner, times(1)).txApplyDestroyPart2(same(existingRegionEntry),
eq(key), eq(inTokenMode),
+ eq(false));
+ }
+
+ @Test
+ public void
txApplyDestroyDoesNotCallsTxApplyDestroyPart2_givenExistingRegionEntry() {
+ givenLocalRegion();
+ givenConcurrencyChecks();
+ givenFactoryRegionEntry();
+ versionTag = mock(VersionTag.class);
+
+ doTxApplyDestroy();
+
+ verify(owner, times(1)).txApplyDestroyPart2(same(factoryRegionEntry),
eq(key), eq(inTokenMode),
+ eq(false));
+ }
+
+ // tests for "factoryRegionEntry" (that is, no existing region entry and no
oldRegionEntry).
+ // All these tests require no existing region entry (that is, not found by
getEntry).
+ // All these tests need one of the following: givenConcurrencyChecks OR
inTokenMode
+
+ @Test
+ public void
txApplyDestroyCallsCreateEntry_givenFactoryRegionEntryAndInTokenMode() {
+ givenLocalRegion();
+ givenFactoryRegionEntry();
+ inTokenMode = true;
+
+ doTxApplyDestroy();
+
+ verify(regionEntryFactory, times(1)).createEntry(same(owner), eq(key),
eq(Token.DESTROYED));
+ }
+
+ @Test
+ public void
txApplyDestroyCallsCreateEntry_givenFactoryRegionEntryAndConcurrencyChecks() {
+ givenLocalRegion();
+ givenFactoryRegionEntry();
+ givenConcurrencyChecks();
+
+ doTxApplyDestroy();
+
+ verify(regionEntryFactory, times(1)).createEntry(same(owner), eq(key),
eq(Token.DESTROYED));
+ }
+
+ @Test
+ public void
txApplyDestroyPreparesAndReleasesIndexManager_givenFactoryRegionEntryAndConcurrencyChecksWithIndexManager()
{
+ givenLocalRegion();
+ givenFactoryRegionEntry();
+ givenConcurrencyChecks();
+ IndexManager indexManager = mock(IndexManager.class);
+ when(owner.getIndexManager()).thenReturn(indexManager);
+
+ doTxApplyDestroy();
+
+ InOrder inOrder = inOrder(indexManager);
+ inOrder.verify(indexManager, times(1)).waitForIndexInit();
+ inOrder.verify(indexManager, times(1)).countDownIndexUpdaters();
+ }
+
+ @Test
+ public void
txApplyDestroyHasNoPendingCallback_givenFactoryRegionEntryWithInTokenModeAndNotInRI()
{
+ givenLocalRegion();
+ givenConcurrencyChecks();
+ givenFactoryRegionEntry();
+ inTokenMode = true;
+ inRI = false;
+
+ doTxApplyDestroy();
+
+ assertThat(pendingCallbacks).isEmpty();
+ }
+
+ @Test
+ public void
txApplyDestroyHasPendingCallback_givenFactoryRegionEntryWithoutInTokenModeAndNotInRI()
{
+ givenLocalRegion();
+ givenConcurrencyChecks();
+ givenFactoryRegionEntry();
+ inTokenMode = false;
+ inRI = false;
+
+ doTxApplyDestroy();
+
+ assertThat(pendingCallbacks).hasSize(1);
+ }
+
+ @Test
+ public void
txApplyDestroyHasPendingCallback_givenFactoryRegionEntryWithoutInTokenModeAndWithInRI()
{
+ givenLocalRegion();
+ givenConcurrencyChecks();
+ givenFactoryRegionEntry();
+ inTokenMode = false;
+ inRI = true;
+
+ doTxApplyDestroy();
+
+ assertThat(pendingCallbacks).hasSize(1);
+ }
+
+ @Test
+ public void
txApplyDestroyHasPendingCallback_givenFactoryRegionEntryWithInTokenModeAndInRI()
{
+ givenLocalRegion();
+ givenConcurrencyChecks();
+ givenFactoryRegionEntry();
+ inTokenMode = true;
+ inRI = true;
+
+ doTxApplyDestroy();
+
+ assertThat(pendingCallbacks).hasSize(1);
+ }
+
+ @Test
+ public void
txApplyDestroyHasNoPendingCallback_givenFactoryRegionEntryWithPartitionedRegion()
{
+ givenBucketRegion();
+ givenConcurrencyChecks();
+ givenFactoryRegionEntry();
+ when(partitionedRegion.getConcurrencyChecksEnabled()).thenReturn(false);
+
+ doTxApplyDestroy();
+
+ assertThat(pendingCallbacks).isEmpty();
+ }
+
+ @Test
+ public void
txApplyDestroyHasNoPendingCallback_givenFactoryRegionEntryWithoutConcurrencyChecksInTokenMode()
{
+ givenLocalRegion();
+ givenFactoryRegionEntry();
+ givenNoConcurrencyChecks();
+ inTokenMode = true;
+
+ doTxApplyDestroy();
+
+ assertThat(pendingCallbacks).isEmpty();
+ }
+
+ @Test
+ public void
txApplyDestroyHasPendingCallback_givenFactoryRegionEntryWithShouldDispatchListenerEvent()
{
+ givenLocalRegion();
+ givenNoConcurrencyChecks();
+ givenFactoryRegionEntry();
+ inTokenMode = true;
+ inRI = true;
+ when(owner.shouldDispatchListenerEvent()).thenReturn(true);
+
+ doTxApplyDestroy();
+
+ assertThat(pendingCallbacks).hasSize(1);
+ }
+
+ @Test
+ public void
txApplyDestroyHasPendingCallback_givenFactoryRegionEntryWithshouldNotifyBridgeClients()
{
+ givenLocalRegion();
+ givenNoConcurrencyChecks();
+ givenFactoryRegionEntry();
+ inTokenMode = true;
+ inRI = true;
+ when(owner.shouldNotifyBridgeClients()).thenReturn(true);
+
+ doTxApplyDestroy();
+
+ assertThat(pendingCallbacks).hasSize(1);
+ }
+
+ @Test
+ public void txApplyDestroySetsRegionEntryOnEvent_givenFactoryRegionEntry() {
+ givenLocalRegion();
+ givenConcurrencyChecks();
+ givenFactoryRegionEntry();
+
+ doTxApplyDestroy();
+
+ EntryEventImpl event = pendingCallbacks.get(0);
+ assertThat(event.getRegionEntry()).isSameAs(factoryRegionEntry);
+ }
+
+ @Test
+ public void
txApplyDestroySetsOldValueOnEventToNotAvailable_givenFactoryRegionEntry() {
+ givenLocalRegion();
+ givenConcurrencyChecks();
+ givenFactoryRegionEntry();
+
+ doTxApplyDestroy();
+
+ EntryEventImpl event = pendingCallbacks.get(0);
+ assertThat(event.getRawOldValue()).isSameAs(Token.NOT_AVAILABLE);
+ }
+
+ @Test
+ public void
txApplyDestroyCallsHandleWanEvent_givenFactoryRegionEntryWithPartitionedRegion()
{
+ givenBucketRegion();
+ givenConcurrencyChecks();
+ givenFactoryRegionEntry();
+
+ doTxApplyDestroy();
+
+ verify(owner, times(1)).handleWANEvent(any());
+ verify(txEntryState, times(1)).setTailKey(tailKey);
+ }
+
+ @Test
+ public void
txApplyDestroyCallsProcessAndGenerateTXVersionTag_givenFactoryRegionEntry() {
+ givenLocalRegion();
+ givenConcurrencyChecks();
+ givenFactoryRegionEntry();
+
+ doTxApplyDestroy();
+
+ verify(regionMap, times(1)).processAndGenerateTXVersionTag(any(),
same(factoryRegionEntry),
+ same(txEntryState));
+ }
+
+ @Test
+ public void
txApplyDestroySetsRemoteOrigin_givenFactoryRegionEntryAndRemoteTxId() {
+ givenLocalRegion();
+ givenConcurrencyChecks();
+ givenFactoryRegionEntry();
+ when(txId.getMemberId()).thenReturn(remoteId);
+
+ doTxApplyDestroy();
+
+ EntryEventImpl event = pendingCallbacks.get(0);
+ assertThat(event.isOriginRemote()).isTrue();
+ }
+
+ @Test
+ public void txApplyDestroySetsRemoteOrigin_givenFactoryRegionEntry() {
+ givenLocalRegion();
+ givenConcurrencyChecks();
+ givenFactoryRegionEntry();
+
+ doTxApplyDestroy();
+
+ EntryEventImpl event = pendingCallbacks.get(0);
+ assertThat(event.isOriginRemote()).isFalse();
+ }
+
+ @Test
+ public void
txApplyDestroySetsRegionOnEvent_givenFactoryRegionEntryAndBucket() {
+ givenBucketRegion();
+ givenConcurrencyChecks();
+ givenFactoryRegionEntry();
+
+ doTxApplyDestroy();
+
+ EntryEventImpl event = pendingCallbacks.get(0);
+ assertThat(event.getRegion()).isSameAs(partitionedRegion);
+ }
+
+ @Test
+ public void txApplyDestroyCallUpdateSizeOnCreate_givenFactoryRegionEntry() {
+ givenLocalRegion();
+ givenConcurrencyChecks();
+ givenFactoryRegionEntry();
+
+ doTxApplyDestroy();
+
+ verify(owner, times(1)).updateSizeOnCreate(eq(key), eq(0));
+ }
+
+ @Test
+ public void
txApplyDestroyCallsMakeTombstone_givenFactoryRegionEntryWithConcurrencyCheckAndVersionTag()
+ throws Exception {
+ givenLocalRegion();
+ givenConcurrencyChecks();
+ givenFactoryRegionEntry();
+ versionTag = mock(VersionTag.class);
+
+ doTxApplyDestroy();
+
+ verify(factoryRegionEntry, times(1)).makeTombstone(same(owner),
same(versionTag));
+ }
+
+ @Test
+ public void
txApplyDestroyNeverCallsMakeTombstone_givenFactoryRegionEntryWithConcurrencyCheckButNoVersionTag()
+ throws Exception {
+ givenLocalRegion();
+ givenConcurrencyChecks();
+ givenFactoryRegionEntry();
+
+ doTxApplyDestroy();
+
+ verify(factoryRegionEntry, never()).makeTombstone(any(), any());
+ }
+
+ @Test
+ public void
txApplyDestroyNeverCallsMakeTombstone_givenFactoryRegionEntryWithoutConcurrencyCheckButWithInTokenModeAndVersionTag()
+ throws Exception {
+ givenLocalRegion();
+ givenNoConcurrencyChecks();
+ givenFactoryRegionEntry();
+ inTokenMode = true;
+ versionTag = mock(VersionTag.class);
+
+ doTxApplyDestroy();
+
+ verify(factoryRegionEntry, never()).makeTombstone(any(), any());
+ }
+
+ @Test
+ public void
txApplyDestroyCallsRemoveEntry_givenFactoryRegionEntryWithConcurrencyCheck()
+ throws Exception {
+ givenLocalRegion();
+ givenConcurrencyChecks();
+ givenFactoryRegionEntry();
+
+ doTxApplyDestroy();
+
+ verify(factoryRegionEntry, times(1)).removePhase1(same(owner), eq(false));
+ verify(factoryRegionEntry, times(1)).removePhase2();
+ verify(regionMap, times(1)).removeEntry(eq(key), same(factoryRegionEntry),
eq(false));
+ }
+
+ @Test
+ public void
txApplyDestroyCallsReleaseEvent_givenFactoryRegionEntryWithoutConcurrencyChecksInTokenMode()
{
+ givenLocalRegion();
+ givenFactoryRegionEntry();
+ givenNoConcurrencyChecks();
+ inTokenMode = true;
+
+ doTxApplyDestroy();
+
+ verify(regionMap, times(1)).releaseEvent(any());
+ }
+
+ @Test
+ public void
txApplyDestroyDoesNotCallSetVersionTag_givenFactoryRegionEntryWithPartitionedRegionButNoConcurrencyChecks()
{
+ givenBucketRegion();
+ givenFactoryRegionEntry();
+ versionTag = mock(VersionTag.class);
+ givenNoConcurrencyChecks();
+ inTokenMode = true;
+
+ doTxApplyDestroy();
+
+ verify(txEntryState, never()).setVersionTag(any());
+ }
+
+ @Test
+ public void
txApplyDestroyDoesNotCallSetVersionTag_givenFactoryRegionEntryWithPartitionedRegionAndConcurrencyChecks()
{
+ givenBucketRegion();
+ givenFactoryRegionEntry();
+ versionTag = mock(VersionTag.class);
+ givenConcurrencyChecks();
+
+ doTxApplyDestroy();
+
+ verify(txEntryState, times(1)).setVersionTag(same(versionTag));
+ }
+
+ @Test
+ public void
txApplyDestroyDoesNotCallTxApplyDestroyPart2_givenFactoryRegionEntryWithMakeTombstoneThrowingRegionDestroyedException()
+ throws Exception {
+ givenLocalRegion();
+ givenConcurrencyChecks();
+ givenFactoryRegionEntry();
+ versionTag = mock(VersionTag.class);
+
doThrow(RegionClearedException.class).when(factoryRegionEntry).makeTombstone(any(),
any());
+
+ doTxApplyDestroy();
+
+ verify(owner, never()).txApplyDestroyPart2(any(), any(), anyBoolean(),
anyBoolean());
+ }
+
+ // tests for "oldRegionEntry" (that is, an existing region entry found by
putIfAbsent).
+ // All these tests require no existing region entry (that is, not found by
getEntry).
+ // All these tests need one of the following: givenConcurrencyChecks OR
inTokenMode
+
+ @Test
+ public void txApplyDestroyRetries_givenOldRegionEntryWithRemovedPhase2() {
+ givenLocalRegion();
+ givenConcurrencyChecks();
+ givenOldRegionEntry();
+ inTokenMode = true;
+ when(oldRegionEntry.isRemovedPhase2()).thenReturn(true).thenReturn(false);
+
+ doTxApplyDestroy();
+
+ verify(cachePerfStats, times(1)).incRetries();
+ verify(entryMap, times(1)).remove(eq(key), same(oldRegionEntry));
+ }
+
+ @Test
+ public void
txApplyDestroyHasNoPendingCallback_givenOldRegionEntryWithInTokenModeAndNotInRI()
{
+ givenLocalRegion();
+ givenConcurrencyChecks();
+ givenOldRegionEntry();
+ inTokenMode = true;
+ inRI = false;
+
+ doTxApplyDestroy();
+
+ assertThat(pendingCallbacks).isEmpty();
+ }
+
+ @Test
+ public void
txApplyDestroyHasPendingCallback_givenOldRegionEntrydWithoutInTokenModeAndNotInRI()
{
+ givenLocalRegion();
+ givenConcurrencyChecks();
+ givenOldRegionEntry();
+ inTokenMode = false;
+ inRI = false;
+
+ doTxApplyDestroy();
+
+ assertThat(pendingCallbacks).hasSize(1);
+ }
+
+ @Test
+ public void
txApplyDestroyHasPendingCallback_givenOldRegionEntryWithoutInTokenModeAndWithInRI()
{
+ givenLocalRegion();
+ givenConcurrencyChecks();
+ givenOldRegionEntry();
+ inTokenMode = false;
+ inRI = true;
+
+ doTxApplyDestroy();
+
+ assertThat(pendingCallbacks).hasSize(1);
+ }
+
+ @Test
+ public void addsCallbackEvent_givenOldRegionEntryWithInTokenModeAndInRI() {
+ givenLocalRegion();
+ givenConcurrencyChecks();
+ givenOldRegionEntry();
+ inTokenMode = true;
+ inRI = true;
+
+ when(owner.generateEventID()).thenReturn(true);
+ when(keyInfo.getCallbackArg()).thenReturn(aCallbackArgument);
+
+ doTxApplyDestroy();
+
+ assertThat(pendingCallbacks).hasSize(1);
+ EntryEventImpl callbackEvent = pendingCallbacks.get(0);
+
+ // noinspection Duplicates
+ assertSoftly(softly -> {
+ softly.assertThat(callbackEvent.getRegion()).isSameAs(owner);
+ softly.assertThat(callbackEvent.getOperation()).isSameAs(operation);
+ softly.assertThat(callbackEvent.getKey()).isSameAs(key);
+ softly.assertThat(callbackEvent.getNewValue()).isNull();
+ softly.assertThat(callbackEvent.getTransactionId()).isSameAs(txId);
+ softly.assertThat(callbackEvent.getEventId()).isSameAs(eventId);
+
softly.assertThat(callbackEvent.getCallbackArgument()).isSameAs(aCallbackArgument);
+
softly.assertThat(callbackEvent.getLocalFilterInfo()).isSameAs(filterRoutingInfo);
+ softly.assertThat(callbackEvent.getContext()).isSameAs(bridgeContext);
+
softly.assertThat(callbackEvent.isOriginRemote()).isEqualTo(isOriginRemote);
+ softly.assertThat(callbackEvent.getVersionTag()).isEqualTo(versionTag);
+ softly.assertThat(callbackEvent.getTailKey()).isEqualTo(tailKey);
+
softly.assertThat(callbackEvent.getRegionEntry()).isSameAs(oldRegionEntry);
+ softly.assertThat(callbackEvent.getOldValue()).isNull();
+ });
+ }
+
+ @Test
+ public void
txApplyDestroyHasNoPendingCallback_givenOldRegionEntryWithPartitionedRegion() {
+ givenBucketRegion();
+ givenConcurrencyChecks();
+ givenOldRegionEntry();
+ when(partitionedRegion.getConcurrencyChecksEnabled()).thenReturn(false);
+
+ doTxApplyDestroy();
+
+ assertThat(pendingCallbacks).isEmpty();
+ }
+
+ @Test
+ public void
txApplyDestroyHasNoPendingCallback_givenOldRegionEntryWithoutConcurrencyChecksInTokenMode()
{
+ givenLocalRegion();
+ givenOldRegionEntry();
+ givenNoConcurrencyChecks();
+ inTokenMode = true;
+
+ doTxApplyDestroy();
+
+ assertThat(pendingCallbacks).isEmpty();
+ }
+
+ @Test
+ public void
txApplyDestroyHasPendingCallback_givenOldRegionEntryWithShouldDispatchListenerEvent()
{
+ givenLocalRegion();
+ givenNoConcurrencyChecks();
+ givenOldRegionEntry();
+ inTokenMode = true;
+ inRI = true;
+ when(owner.shouldDispatchListenerEvent()).thenReturn(true);
+
+ doTxApplyDestroy();
+
+ assertThat(pendingCallbacks).hasSize(1);
+ }
+
+ @Test
+ public void
txApplyDestroyHasPendingCallback_givenOldRegionEntryWithshouldNotifyBridgeClients()
{
+ givenLocalRegion();
+ givenNoConcurrencyChecks();
+ givenOldRegionEntry();
+ inTokenMode = true;
+ inRI = true;
+ when(owner.shouldNotifyBridgeClients()).thenReturn(true);
+
+ doTxApplyDestroy();
+
+ assertThat(pendingCallbacks).hasSize(1);
+ }
+
+ @Test
+ public void txApplyDestroySetsRegionEntryOnEvent_givenOldRegionEntry() {
+ givenLocalRegion();
+ givenConcurrencyChecks();
+ givenOldRegionEntry();
+
+ doTxApplyDestroy();
+
+ EntryEventImpl event = pendingCallbacks.get(0);
+ assertThat(event.getRegionEntry()).isSameAs(oldRegionEntry);
+ }
+
+ @Test
+ public void
txApplyDestroySetsOldValueOnEventToNotAvailable_givenOldRegionEntry() {
+ givenLocalRegion();
+ givenConcurrencyChecks();
+ givenOldRegionEntry();
+
+ doTxApplyDestroy();
+
+ EntryEventImpl event = pendingCallbacks.get(0);
+ assertThat(event.getRawOldValue()).isSameAs(Token.NOT_AVAILABLE);
+ }
+
+ @Test
+ public void
txApplyDestroyCallsHandleWanEvent_givenOldRegionEntryWithPartitionedRegion() {
+ givenBucketRegion();
+ givenConcurrencyChecks();
+ givenOldRegionEntry();
+
+ doTxApplyDestroy();
+
+ verify(owner, times(1)).handleWANEvent(any());
+ verify(txEntryState, times(1)).setTailKey(tailKey);
+ }
+
+ @Test
+ public void
txApplyDestroyCallsProcessAndGenerateTXVersionTag_givenOldRegionEntry() {
+ givenLocalRegion();
+ givenConcurrencyChecks();
+ givenOldRegionEntry();
+
+ doTxApplyDestroy();
+
+ verify(regionMap, times(1)).processAndGenerateTXVersionTag(any(),
same(oldRegionEntry),
+ same(txEntryState));
+ }
+
+ @Test
+ public void
txApplyDestroySetsRemoteOrigin_givenOldRegionEntryAndRemoteTxId() {
+ givenLocalRegion();
+ givenConcurrencyChecks();
+ givenOldRegionEntry();
+ when(txId.getMemberId()).thenReturn(remoteId);
+
+ doTxApplyDestroy();
+
+ EntryEventImpl event = pendingCallbacks.get(0);
+ assertThat(event.isOriginRemote()).isTrue();
+ }
+
+ @Test
+ public void txApplyDestroySetsRemoteOrigin_givenOldRegionEntry() {
+ givenLocalRegion();
+ givenConcurrencyChecks();
+ givenOldRegionEntry();
+
+ doTxApplyDestroy();
+
+ EntryEventImpl event = pendingCallbacks.get(0);
+ assertThat(event.isOriginRemote()).isFalse();
+ }
+
+ @Test
+ public void addsCallbackEvent_givenOldRegionEntryAndBucket() {
+ givenBucketRegion();
+ givenConcurrencyChecks();
+ givenOldRegionEntry();
+
+ when(partitionedRegion.generateEventID()).thenReturn(true);
+ when(keyInfo.getCallbackArg()).thenReturn(aCallbackArgument);
+
+ doTxApplyDestroy();
+
+ EntryEventImpl callbackEvent = pendingCallbacks.get(0);
+
+ // noinspection Duplicates
+ assertSoftly(softly -> {
+ softly.assertThat(callbackEvent.getRegion()).isSameAs(partitionedRegion);
+ softly.assertThat(callbackEvent.getOperation()).isSameAs(operation);
+ softly.assertThat(callbackEvent.getKey()).isSameAs(key);
+ softly.assertThat(callbackEvent.getNewValue()).isNull();
+ softly.assertThat(callbackEvent.getTransactionId()).isSameAs(txId);
+ softly.assertThat(callbackEvent.getEventId()).isSameAs(eventId);
+
softly.assertThat(callbackEvent.getCallbackArgument()).isSameAs(aCallbackArgument);
+
softly.assertThat(callbackEvent.getLocalFilterInfo()).isSameAs(filterRoutingInfo);
+ softly.assertThat(callbackEvent.getContext()).isSameAs(bridgeContext);
+
softly.assertThat(callbackEvent.isOriginRemote()).isEqualTo(isOriginRemote);
+ softly.assertThat(callbackEvent.getVersionTag()).isEqualTo(versionTag);
+ softly.assertThat(callbackEvent.getTailKey()).isEqualTo(tailKey);
+
softly.assertThat(callbackEvent.getRegionEntry()).isSameAs(oldRegionEntry);
+ softly.assertThat(callbackEvent.getOldValue()).isNull();
+ });
+ }
+
+ @Test
+ public void
txApplyDestroyCallUpdateSizeOnRemoveWithZero_givenOldRegionEntryThatIsTombstone()
{
+ givenLocalRegion();
+ givenConcurrencyChecks();
+ givenOldRegionEntry();
+ when(oldRegionEntry.isTombstone()).thenReturn(true);
+
+ doTxApplyDestroy();
+
+ verify(owner, times(1)).updateSizeOnRemove(eq(key), eq(0));
+ }
+
+ @Test
+ public void
txApplyDestroyCallUpdateSizeOnRemoveWithOldSize_givenOldRegionEntryThatIsNotTombstone()
{
+ givenLocalRegion();
+ givenConcurrencyChecks();
+ givenOldRegionEntry();
+ int oldSize = 79;
+
when(owner.calculateRegionEntryValueSize(oldRegionEntry)).thenReturn(oldSize);
+ when(oldRegionEntry.isTombstone()).thenReturn(false);
+
+ doTxApplyDestroy();
+
+ verify(owner, times(1)).updateSizeOnRemove(eq(key), eq(oldSize));
+ }
+
+ @Test
+ public void txApplyDestroySetsValueToTokenDestroyed_givenOldRegionEntry()
throws Exception {
+ givenLocalRegion();
+ givenConcurrencyChecks();
+ givenOldRegionEntry();
+
+ doTxApplyDestroy();
+
+ verify(oldRegionEntry, times(1)).setValue(same(owner),
eq(Token.DESTROYED));
+ }
+
+ @Test
+ public void
txApplyDestroySetsValueToTokenDestroyed_givenOldRegionEntryAndInTokenMode()
+ throws Exception {
+ givenLocalRegion();
+ givenNoConcurrencyChecks();
+ givenOldRegionEntry();
+ inTokenMode = true;
+
+ doTxApplyDestroy();
+
+ verify(oldRegionEntry, times(1)).setValue(same(owner),
eq(Token.DESTROYED));
+ }
+
+ @Test
+ public void
txApplyDestroyCallsUnscheduleTombstone_givenOldRegionEntryThatIsTombstone() {
+ givenLocalRegion();
+ givenConcurrencyChecks();
+ givenOldRegionEntry();
+ when(oldRegionEntry.isTombstone()).thenReturn(true);
+
+ doTxApplyDestroy();
+
+ verify(owner, times(1)).unscheduleTombstone(same(oldRegionEntry));
+ }
+
+ @Test
+ public void txApplyDestroyCallsTxApplyDestroyPart2_givenOldRegionEntry() {
+ givenLocalRegion();
+ givenConcurrencyChecks();
+ givenOldRegionEntry();
+
+ doTxApplyDestroy();
+
+ verify(owner, times(1)).txApplyDestroyPart2(same(oldRegionEntry), eq(key),
eq(inTokenMode),
+ eq(false));
+ }
+
+ @Test
+ public void
txApplyDestroyCallsTxApplyDestroyPart2_givenOldRegionEntryWithInTokenMode() {
+ givenLocalRegion();
+ givenConcurrencyChecks();
+ givenOldRegionEntry();
+ inTokenMode = true;
+
+ doTxApplyDestroy();
+
+ verify(owner, times(1)).txApplyDestroyPart2(same(oldRegionEntry), eq(key),
eq(inTokenMode),
+ eq(false));
+ }
+
+ @Test
+ public void txApplyDestroyCallsLruEntryDestroy_givenOldRegionEntry() {
+ givenLocalRegion();
+ givenConcurrencyChecks();
+ givenOldRegionEntry();
+
+ doTxApplyDestroy();
+
+ verify(regionMap, times(1)).lruEntryDestroy(oldRegionEntry);
+ }
+
+ @Test
+ public void
txApplyDestroyCallsReleaseEvent_givenOldRegionEntryWithoutConcurrencyChecksInTokenMode()
{
+ givenLocalRegion();
+ givenOldRegionEntry();
+ givenNoConcurrencyChecks();
+ inTokenMode = true;
+
+ doTxApplyDestroy();
+
+ verify(regionMap, times(1)).releaseEvent(any());
+ }
+
+ @Test
+ public void
txApplyDestroyDoesCallTxApplyDestroyPart2_givenOldRegionEntryWithMakeTombstoneThrowingRegionDestroyedException()
+ throws Exception {
+ givenLocalRegion();
+ givenConcurrencyChecks();
+ givenOldRegionEntry();
+ doThrow(RegionClearedException.class).when(oldRegionEntry).setValue(any(),
any());
+
+ doTxApplyDestroy();
+
+ verify(owner, times(1)).txApplyDestroyPart2(same(oldRegionEntry), eq(key),
eq(inTokenMode),
+ eq(true));
+ }
+
+ @Test
+ public void
txApplyDestroyCallsMakeTombstone_givenOldRegionEntryWithConcurrencyCheckAndVersionTag()
+ throws Exception {
+ givenLocalRegion();
+ givenConcurrencyChecks();
+ givenOldRegionEntry();
+ versionTag = mock(VersionTag.class);
+
+ doTxApplyDestroy();
+
+ verify(oldRegionEntry, times(1)).makeTombstone(same(owner),
same(versionTag));
+ }
+
+ @Test
+ public void txApplyDestroyCallsRemoveEntry_givenOldRegionEntry() throws
Exception {
+ givenLocalRegion();
+ givenConcurrencyChecks();
+ givenOldRegionEntry();
+
+ doTxApplyDestroy();
+
+ verify(oldRegionEntry, never()).makeTombstone(any(), any());
+ verify(oldRegionEntry, times(1)).removePhase1(same(owner), eq(false));
+ verify(oldRegionEntry, times(1)).removePhase2();
+ verify(regionMap, times(1)).removeEntry(eq(key), same(oldRegionEntry),
eq(false));
+ }
+
+ @Test
+ public void
txApplyDestroyNeverCallsRemoveEntry_givenOldRegionEntryAndInTokenMode()
+ throws Exception {
+ givenLocalRegion();
+ givenConcurrencyChecks();
+ givenOldRegionEntry();
+ inTokenMode = true;
+
+ doTxApplyDestroy();
+
+ verify(oldRegionEntry, never()).makeTombstone(any(), any());
+ verify(oldRegionEntry, never()).removePhase1(any(), anyBoolean());
+ verify(oldRegionEntry, never()).removePhase2();
+ verify(regionMap, never()).removeEntry(any(), any(), anyBoolean());
+ }
+
+ @Test
+ public void
txApplyDestroyDoesCallsHandleDiskAccessException_givenOldRegionEntrySetValueThatThrowsDiskAccessException()
+ throws Exception {
+ givenLocalRegion();
+ givenConcurrencyChecks();
+ givenOldRegionEntry();
+ doThrow(DiskAccessException.class).when(oldRegionEntry).setValue(any(),
any());
+
+
assertThatThrownBy(this::doTxApplyDestroy).isInstanceOf(DiskAccessException.class);
+
+ verify(owner, times(1)).handleDiskAccessException(any());
+ }
+
+ // helper methods for the tests
+
+ private void givenNoRegionEntry() {
+ when(entryMap.get(eq(key))).thenReturn(null);
+ }
+
+ private void givenExistingRegionEntry() {
+ when(entryMap.get(eq(key))).thenReturn(existingRegionEntry);
+ }
+
+ private void givenFactoryRegionEntry() {
+ when(entryMap.get(eq(key))).thenReturn(null);
+ when(regionEntryFactory.createEntry(any(), any(),
any())).thenReturn(factoryRegionEntry);
+ }
+
+ private void givenOldRegionEntry() {
+ when(entryMap.get(eq(key))).thenReturn(null);
+ when(regionEntryFactory.createEntry(any(), any(),
any())).thenReturn(factoryRegionEntry);
+ when(entryMap.putIfAbsent(eq(key),
same(factoryRegionEntry))).thenReturn(oldRegionEntry);
+ }
+
+ private void givenNotInTokenMode() {
+ inTokenMode = false;
+ }
+
+ private void givenConcurrencyChecks() {
+ when(owner.getConcurrencyChecksEnabled()).thenReturn(true);
+ when(partitionedRegion.getConcurrencyChecksEnabled()).thenReturn(true);
+ }
+
+ private void givenNoConcurrencyChecks() {
+ when(owner.getConcurrencyChecksEnabled()).thenReturn(false);
+ }
+
+ private void givenLocalRegion() {
+ owner = mock(LocalRegion.class);
+ setupLocalRegion();
+ regionMap = spy(new TestableAbstractRegionMap());
+ }
+
+ private void givenBucketRegion() {
+ BucketRegion bucketRegion = mock(BucketRegion.class);
+ when(bucketRegion.isUsedForPartitionedRegionBucket()).thenReturn(true);
+ when(bucketRegion.getPartitionedRegion()).thenReturn(partitionedRegion);
+
when(bucketRegion.getBucketAdvisor()).thenReturn(mock(BucketAdvisor.class));
+ owner = bucketRegion;
+ setupLocalRegion();
+ regionMap = spy(new TestableAbstractRegionMap());
+ }
+
+ private void setupLocalRegion() {
+ when(owner.getCachePerfStats()).thenReturn(cachePerfStats);
+ when(owner.getCache()).thenReturn(mock(InternalCache.class));
+ when(owner.getMyId()).thenReturn(myId);
+ when(owner.getKeyInfo(any(), any(), any())).thenReturn(keyInfo);
+ }
+
+ private void doTxApplyDestroy() {
+ regionMap.txApplyDestroy(key, txId, txEvent, inTokenMode, inRI, operation,
eventId,
+ aCallbackArgument, pendingCallbacks, filterRoutingInfo, bridgeContext,
isOriginRemote,
+ txEntryState, versionTag, tailKey);
+ }
+
+ private class TestableAbstractRegionMap extends AbstractRegionMap {
+
+ TestableAbstractRegionMap() {
+ super(null);
+ initialize(owner, new Attributes(), null, false);
+ setEntryMap(entryMap);
+ setEntryFactory(regionEntryFactory);
+ }
+
+ }
+}
--
To stop receiving notification emails like this one, please contact
[email protected].