/*
 * 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, Version 2.0 (the
 * "License"); you may not use this file except in compliance with the License. You may obtain a
 * copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software distributed under the License
 * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
 * or implied. See the License for the specific language governing permissions and limitations under
 * the License.
 */
package org.apache.geode.cache30;

import static org.apache.geode.internal.lang.ThrowableUtils.hasCauseMessage;
import static org.apache.geode.test.awaitility.GeodeAwaitility.await;
import static org.apache.geode.test.dunit.Invoke.invokeInEveryVM;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.assertj.core.api.Assertions.fail;
import static org.assertj.core.api.Assumptions.assumeThat;
import static org.assertj.core.api.SoftAssertions.assertSoftly;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.greaterThanOrEqualTo;

import java.io.ByteArrayInputStream;
import java.io.DataInput;
import java.io.DataInputStream;
import java.io.DataOutput;
import java.io.IOException;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Random;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.stream.Stream;

import org.apache.logging.log4j.Logger;
import org.awaitility.core.ConditionTimeoutException;
import org.junit.AfterClass;
import org.junit.Ignore;
import org.junit.Test;

import org.apache.geode.DataSerializable;
import org.apache.geode.DataSerializer;
import org.apache.geode.Instantiator;
import org.apache.geode.InvalidDeltaException;
import org.apache.geode.cache.AttributesFactory;
import org.apache.geode.cache.AttributesMutator;
import org.apache.geode.cache.Cache;
import org.apache.geode.cache.CacheEvent;
import org.apache.geode.cache.CacheException;
import org.apache.geode.cache.CacheListener;
import org.apache.geode.cache.CacheLoader;
import org.apache.geode.cache.CacheLoaderException;
import org.apache.geode.cache.CacheTransactionManager;
import org.apache.geode.cache.CacheWriter;
import org.apache.geode.cache.CacheWriterException;
import org.apache.geode.cache.DataPolicy;
import org.apache.geode.cache.EntryEvent;
import org.apache.geode.cache.EntryExistsException;
import org.apache.geode.cache.EntryNotFoundException;
import org.apache.geode.cache.ExpirationAction;
import org.apache.geode.cache.ExpirationAttributes;
import org.apache.geode.cache.InterestPolicy;
import org.apache.geode.cache.LoaderHelper;
import org.apache.geode.cache.Operation;
import org.apache.geode.cache.Region;
import org.apache.geode.cache.RegionAttributes;
import org.apache.geode.cache.RegionEvent;
import org.apache.geode.cache.RegionFactory;
import org.apache.geode.cache.RegionShortcut;
import org.apache.geode.cache.Scope;
import org.apache.geode.cache.SubscriptionAttributes;
import org.apache.geode.cache.TimeoutException;
import org.apache.geode.cache.TransactionEvent;
import org.apache.geode.cache.TransactionId;
import org.apache.geode.cache.TransactionListener;
import org.apache.geode.cache.partition.PartitionRegionHelper;
import org.apache.geode.cache.server.CacheServer;
import org.apache.geode.cache.util.CacheListenerAdapter;
import org.apache.geode.cache.util.TxEventTestUtil;
import org.apache.geode.distributed.ConfigurationProperties;
import org.apache.geode.distributed.internal.DMStats;
import org.apache.geode.distributed.internal.DistributionConfig;
import org.apache.geode.distributed.internal.membership.InternalDistributedMember;
import org.apache.geode.internal.AvailablePortHelper;
import org.apache.geode.internal.HeapDataOutputStream;
import org.apache.geode.internal.InternalDataSerializer;
import org.apache.geode.internal.InternalInstantiator;
import org.apache.geode.internal.Version;
import org.apache.geode.internal.cache.EntryExpiryTask;
import org.apache.geode.internal.cache.ExpiryTask;
import org.apache.geode.internal.cache.GemFireCacheImpl;
import org.apache.geode.internal.cache.InitialImageOperation;
import org.apache.geode.internal.cache.LocalRegion;
import org.apache.geode.internal.cache.PartitionedRegion;
import org.apache.geode.internal.cache.RegionEntry;
import org.apache.geode.internal.cache.TXManagerImpl;
import org.apache.geode.internal.cache.TXStateProxy;
import org.apache.geode.internal.cache.Token;
import org.apache.geode.internal.cache.TombstoneService;
import org.apache.geode.internal.cache.versions.RegionVersionVector;
import org.apache.geode.internal.cache.versions.VersionSource;
import org.apache.geode.internal.cache.versions.VersionTag;
import org.apache.geode.internal.logging.LogService;
import org.apache.geode.internal.offheap.MemoryAllocatorImpl;
import org.apache.geode.internal.offheap.StoredObject;
import org.apache.geode.test.dunit.AsyncInvocation;
import org.apache.geode.test.dunit.DistributedTestUtils;
import org.apache.geode.test.dunit.IgnoredException;
import org.apache.geode.test.dunit.SerializableCallable;
import org.apache.geode.test.dunit.SerializableRunnable;
import org.apache.geode.test.dunit.SerializableRunnableIF;
import org.apache.geode.test.dunit.ThreadUtils;
import org.apache.geode.test.dunit.VM;
import org.apache.geode.test.dunit.Wait;
import org.apache.geode.test.dunit.internal.DUnitLauncher;

/**
 * Abstract superclass of {@link Region} tests that involve more than one VM.
 */
public abstract class MultiVMRegionTestCase extends RegionTestCase {
  private static final Logger logger = LogService.getLogger();
  private static final long POLL_INTERVAL_MILLIS = 50;

  private static final int PUT_RANGE_1_START = 1;
  private static final int PUT_RANGE_1_END = 5;
  private static final int PUT_RANGE_2_START = 6;
  private static final int PUT_RANGE_2_END = 10;

  private static TestCacheListener testCacheListener;
  private static TestCacheLoader testCacheLoader;
  private static TestCacheWriter testCacheWriter;

  private static int afterCreates;

  static LocalRegion CCRegion;
  static int distributedSystemID;

  @SuppressWarnings("unchecked")
  private static <K, V> TestCacheListener<K, V> listener() {
    return testCacheListener;
  }

  private static <K, V> void setListener(TestCacheListener<K, V> listener) {
    testCacheListener = listener;
  }

  @SuppressWarnings("unchecked")
  protected static <K, V> TestCacheLoader<K, V> loader() {
    return testCacheLoader;
  }

  protected static <K, V> void setLoader(TestCacheLoader<K, V> loader) {
    testCacheLoader = loader;
  }

  @SuppressWarnings("unchecked")
  private static <K, V> TestCacheWriter<K, V> writer() {
    return testCacheWriter;
  }

  private static <K, V> void setWriter(TestCacheWriter<K, V> writer) {
    testCacheWriter = writer;
  }

  private static void cleanup() {
    testCacheListener = null;
    testCacheLoader = null;
    testCacheWriter = null;
    CCRegion = null;
  }

  @AfterClass
  public static void caseTearDown() {
    disconnectAllFromDS();
  }

  @SuppressWarnings("RedundantThrows") // Subclasses may want to throw
  @Override
  protected final void postTearDownRegionTestCase() throws Exception {
    cleanup();
    invokeInEveryVM(MultiVMRegionTestCase::cleanup);
  }

  @Override
  public Properties getDistributedSystemProperties() {
    Properties properties = super.getDistributedSystemProperties();
    properties.put(ConfigurationProperties.SERIALIZABLE_OBJECT_FILTER,
        "org.apache.geode.cache30.MultiVMRegionTestCase$DeltaValue");
    return properties;
  }

  /**
   * This is a for the ConcurrentMap operations. 4 VMs are used to create the region and operations
   * are performed on one of the nodes
   */
  @Test
  public void testConcurrentOperations() {
    SerializableRunnable createRegion = new CacheSerializableRunnable("createRegion") {

      @Override
      public void run2() throws CacheException {
        Cache cache = getCache();
        RegionAttributes<?, ?> regionAttribs = getRegionAttributes();
        cache.createRegionFactory(regionAttribs).create("R1");
      }
    };

    // create the VM(0 - 4)
    VM vm0 = VM.getVM(0);
    VM vm1 = VM.getVM(1);
    VM vm2 = VM.getVM(2);
    VM vm3 = VM.getVM(3);
    vm0.invoke(createRegion);
    vm1.invoke(createRegion);
    vm2.invoke(createRegion);
    vm3.invoke(createRegion);
    concurrentMapTest("/R1");
  }

  /**
   * Do putIfAbsent(), replace(Object, Object), replace(Object, Object, Object), remove(Object,
   * Object) operations
   */
  private void concurrentMapTest(final String rName) {

    // String exceptionStr = "";
    VM vm0 = VM.getVM(0);

    vm0.invoke(new CacheSerializableRunnable("doConcurrentMapOperations") {
      @Override
      public void run2() throws CacheException {
        Cache cache = getCache();
        final Region<String, String> pr = cache.getRegion(rName);
        assertThat(pr).describedAs(rName + " not created").isNotNull();

        // test successful putIfAbsent
        for (int i = PUT_RANGE_1_START; i <= PUT_RANGE_1_END; i++) {
          Object putResult = pr.putIfAbsent(Integer.toString(i), Integer.toString(i));
          assertThat(putResult).describedAs("Expected null, but got " + putResult + " for key " + i)
              .isNull();
        }
        int size = pr.size();
        assertThat(size).describedAs("Size doesn't return expected value")
            .isEqualTo(PUT_RANGE_1_END);
        assertThat(pr.isEmpty()).describedAs("isEmpty doesn't return proper state of the region")
            .isFalse();

        // test unsuccessful putIfAbsent
        for (int i = PUT_RANGE_1_START; i <= PUT_RANGE_1_END; i++) {
          Object putResult = pr.putIfAbsent(Integer.toString(i), Integer.toString(i + 1));
          assertThat(putResult).describedAs("for i=" + i).isEqualTo(Integer.toString(i));
          assertThat(pr.get(Integer.toString(i))).describedAs("for i=" + i).isEqualTo(
              Integer.toString(i));
        }
        size = pr.size();
        assertThat(size).describedAs("Size doesn't return expected value")
            .isEqualTo(PUT_RANGE_1_END);
        assertThat(pr.isEmpty()).describedAs("isEmpty doesn't return proper state of the region")
            .isFalse();

        // test successful replace(key, oldValue, newValue)
        for (int i = PUT_RANGE_1_START; i <= PUT_RANGE_1_END; i++) {
          boolean replaceSucceeded =
              pr.replace(Integer.toString(i), Integer.toString(i), "replaced" + i);
          assertThat(replaceSucceeded).describedAs("for i=" + i).isTrue();
          assertThat(pr.get(Integer.toString(i))).describedAs("for i=" + i).isEqualTo(
              ("replaced" + i));
        }
        size = pr.size();
        assertThat(size).describedAs("Size doesn't return expected value").isEqualTo(
            PUT_RANGE_1_END);
        assertThat(pr.isEmpty()).describedAs("isEmpty doesn't return proper state of the region")
            .isFalse();

        // test unsuccessful replace(key, oldValue, newValue)
        for (int i = PUT_RANGE_1_START; i <= PUT_RANGE_2_END; i++) {
          boolean replaceSucceeded = pr.replace(Integer.toString(i), Integer.toString(i), // wrong
              // expected
              // old
              // value
              "not" + i);
          assertThat(replaceSucceeded).describedAs("for i=" + i).isFalse();
          Object expected1 = i <= PUT_RANGE_1_END ? "replaced" + i : null;
          assertThat(pr.get(Integer.toString(i))).describedAs("for i=" + i).isEqualTo(
              expected1);
        }
        size = pr.size();
        assertThat(size).describedAs("Size doesn't return expected value").isEqualTo(
            PUT_RANGE_1_END);
        assertThat(pr.isEmpty()).describedAs("isEmpty doesn't return proper state of the region")
            .isFalse();

        // test successful replace(key, value)
        for (int i = PUT_RANGE_1_START; i <= PUT_RANGE_1_END; i++) {
          Object replaceResult = pr.replace(Integer.toString(i), "twice replaced" + i);
          assertThat(replaceResult).describedAs("for i=" + i).isEqualTo(("replaced" + i));
          assertThat(pr.get(Integer.toString(i))).describedAs("for i=" + i).isEqualTo(
              ("twice replaced" + i));
        }
        size = pr.size();
        assertThat(size).describedAs("Size doesn't return expected value").isEqualTo(
            PUT_RANGE_1_END);
        assertThat(pr.isEmpty()).describedAs("isEmpty doesn't return proper state of the region")
            .isFalse();

        // test unsuccessful replace(key, value)
        for (int i = PUT_RANGE_2_START; i <= PUT_RANGE_2_END; i++) {
          Object replaceResult = pr.replace(Integer.toString(i), "thrice replaced" + i);
          assertThat(replaceResult).describedAs("for i=" + i).isNull();
          assertThat(pr.get(Integer.toString(i))).describedAs("for i=" + i).isNull();
        }
        size = pr.size();
        assertThat(size).describedAs("Size doesn't return expected value").isEqualTo(
            PUT_RANGE_1_END);
        assertThat(pr.isEmpty()).describedAs("isEmpty doesn't return proper state of the region")
            .isFalse();

        // test unsuccessful remove(key, value)
        for (int i = PUT_RANGE_1_START; i <= PUT_RANGE_2_END; i++) {
          boolean removeResult = pr.remove(Integer.toString(i), Integer.toString(-i));
          assertThat(removeResult).describedAs("for i=" + i).isFalse();
          Object expected1 =
              i <= PUT_RANGE_1_END ? "twice replaced" + i : null;
          assertThat(pr.get(Integer.toString(i))).describedAs("for i=" + i).isEqualTo(
              expected1);
        }
        size = pr.size();
        assertThat(size).describedAs("Size doesn't return expected value").isEqualTo(
            PUT_RANGE_1_END);
        assertThat(pr.isEmpty()).describedAs("isEmpty doesn't return proper state of the region")
            .isFalse();

        // test successful remove(key, value)
        for (int i = PUT_RANGE_1_START; i <= PUT_RANGE_1_END; i++) {
          boolean removeResult = pr.remove(Integer.toString(i), "twice replaced" + i);
          assertThat(removeResult).describedAs("for i=" + i).isTrue();
          assertThat(pr.get(Integer.toString(i))).describedAs("for i=" + i).isNull();
        }
        size = pr.size();
        assertThat(size).describedAs("Size doesn't return expected value").isEqualTo(0);
        assertThat(pr.isEmpty()).describedAs("isEmpty doesn't return proper state of the region")
            .isTrue();
      }
    });


    /*
     * destroy the Region.
     */
    vm0.invoke(new CacheSerializableRunnable("destroyRegionOp") {

      @Override
      public void run2() {
        Cache cache = getCache();
        Region<?, ?> pr = cache.getRegion(rName);
        assertThat(pr).describedAs("Region already destroyed.").isNotNull();
        pr.destroyRegion();
        assertThat(pr.isDestroyed()).describedAs("Region isDestroyed false").isTrue();
        assertThat(cache.getRegion(rName)).describedAs("Region not destroyed.").isNull();
      }
    });
  }

  /**
   * Tests that doing a {@link Region#put put} in a distributed region one VM updates the value in
   * another VM.
   */
  @Test
  public void testDistributedUpdate() {
    boolean condition = getRegionAttributes().getScope().isDistributed();
    assertThat(condition).isTrue();

    final String name = this.getUniqueName();

    SerializableRunnable create = new CacheSerializableRunnable("Create Region") {
      @Override
      public void run2() throws CacheException {
        createRegion(name);
      }
    };

    VM vm0 = VM.getVM(0);
    VM vm1 = VM.getVM(1);
    vm0.invoke(create);
    vm1.invoke(create);

    final Object key = "KEY";
    final Object oldValue = "OLD_VALUE";
    final Object newValue = "NEW_VALUE";

    SerializableRunnable put = new CacheSerializableRunnable("Put key/value") {
      @Override
      public void run2() throws CacheException {
        Region<Object, Object> region = getRootRegion().getSubregion(name);
        region.put(key, oldValue);
        flushIfNecessary(region);
      }
    };

    vm0.invoke(put);
    vm1.invoke(put);

    vm0.invoke(new CacheSerializableRunnable("Update") {
      @Override
      public void run2() throws CacheException {
        Region<Object, Object> region = getRootRegion().getSubregion(name);
        region.put(key, newValue);
        flushIfNecessary(region);
      }
    });

    vm1.invoke(new CacheSerializableRunnable("Validate update") {
      @Override
      public void run2() throws CacheException {
        Region<Object, Object> region = getRootRegion().getSubregion(name);
        Region.Entry entry = region.getEntry(key);
        assertThat(entry).isNotNull();
        assertThat(entry.getValue()).isEqualTo(newValue);
      }
    });
  }

  /**
   * Verifies that distributed updates are delivered in order.
   *
   * <p>
   * Note that this test does not make sense for regions that are {@link Scope#DISTRIBUTED_NO_ACK}
   * for which we do not guarantee the ordering of updates for a single producer/single consumer.
   */
  @Test
  public void testOrderedUpdates() throws Exception {
    assumeThat(getRegionAttributes().getScope()).isNotEqualTo(Scope.DISTRIBUTED_NO_ACK);

    final String regionName = getUniqueName();
    final String key = "KEY";
    final int lastValue = 10;

    VM vm0 = VM.getVM(0);
    VM vm1 = VM.getVM(1);

    vm0.invoke("Create region", () -> {
      createRegion(regionName);
    });

    vm1.invoke("Create region and region entry", () -> {
      Region<String, Integer> region = createRegion(regionName);
      region.create(key, null);
    });

    vm1.invoke("Set listener", () -> {
      Region<String, Integer> region = getRootRegion().getSubregion(regionName);
      region.setUserAttribute(new LinkedBlockingQueue<Integer>());

      region.getAttributesMutator().addCacheListener(new CacheListenerAdapter<String, Integer>() {
        @Override
        public void afterUpdate(EntryEvent<String, Integer> event) {
          Region<String, Integer> region = event.getRegion();
          @SuppressWarnings("unchecked")
          BlockingQueue<Integer> queue = (BlockingQueue<Integer>) region.getUserAttribute();
          int value = event.getNewValue();
          try {
            queue.put(value);
          } catch (InterruptedException e) {
            throw new RuntimeException(e);
          }
        }
      });
      flushIfNecessary(region);
    });

    AsyncInvocation verify = vm1.invokeAsync("Verify", () -> {
      Region<String, Integer> region = getRootRegion().getSubregion(regionName);
      @SuppressWarnings("unchecked")
      BlockingQueue<Integer> queue = (BlockingQueue<Integer>) region.getUserAttribute();
      for (int i = 0; i <= lastValue; i++) {
        try {
          int value = queue.take();
          assertThat(value).isEqualTo(i);
        } catch (InterruptedException e) {
          throw new RuntimeException(e);
        }
      }
    });

    AsyncInvocation populate = vm0.invokeAsync("Populate", () -> {
      Region<String, Integer> region = getRootRegion().getSubregion(regionName);
      for (int i = 0; i <= lastValue; i++) {
        region.put(key, i);
      }
    });

    populate.await();
    verify.await();
  }

  /**
   * Tests that doing a distributed get results in a <code>netSearch</code>.
   */
  @Test
  public void testDistributedGet() {
    assertThat(getRegionAttributes().getScope().isDistributed()).isTrue();

    final String name = this.getUniqueName();
    final Object key = "KEY";
    final Object value = "VALUE";

    VM vm0 = VM.getVM(0);
    VM vm1 = VM.getVM(1);

    vm0.invoke(new CacheSerializableRunnable("Populate region") {
      @Override
      public void run2() throws CacheException {
        Region<Object, Object> region = createRegion(name);
        region.put(key, value);
      }
    });

    SerializableRunnable get = new CacheSerializableRunnable("Distributed get") {
      @Override
      public void run2() throws CacheException {
        Region<Object, Object> region = createRegion(name);
        assertThat(region.get(key)).isEqualTo(value);
      }
    };

    vm1.invoke(get);
  }

  /**
   * Tests that doing a {@link Region#put put} on a distributed region in one VM does not effect a
   * region in a different VM that does not have that key defined.
   */
  @Test
  public void testDistributedPutNoUpdate() throws Exception {
    assertThat(getRegionAttributes().getScope().isDistributed()).isTrue();

    final String name = this.getUniqueName();

    SerializableRunnable create = new CacheSerializableRunnable("Create Region") {
      @Override
      public void run2() throws CacheException {
        createRegion(name);
      }
    };

    VM vm0 = VM.getVM(0);
    VM vm1 = VM.getVM(1);

    vm0.invoke(create);
    vm1.invoke(create);

    Thread.sleep(250);

    final Object key = "KEY";
    final Object value = "VALUE";

    vm0.invoke(new CacheSerializableRunnable("Put key/value") {
      @Override
      public void run2() throws CacheException {
        Region<Object, Object> region = getRootRegion().getSubregion(name);
        region.put(key, value);
      }
    });

    Thread.sleep(250);

    vm1.invoke(new CacheSerializableRunnable("Verify no update") {
      @Override
      public void run2() throws CacheException {
        Region<Object, Object> region = getRootRegion().getSubregion(name);
        Region.Entry entry = region.getEntry(key);
        if (getRegionAttributes().getDataPolicy().withReplication()
            || getRegionAttributes().getPartitionAttributes() != null) {
          assertThat(region.get(key)).isEqualTo(value);
        } else {
          assertThat(entry).isNull();
        }
      }
    });
  }

  /**
   * Two VMs create a region. One populates a region entry. The other VM defines that entry. The
   * first VM updates the entry. The second VM should see the updated value.
   */
  @Test
  public void testDefinedEntryUpdated() {
    final String name = this.getUniqueName();
    final Object key = "KEY";
    final Object oldValue = "OLD_VALUE";
    final Object newValue = "NEW_VALUE";

    VM vm0 = VM.getVM(0);
    VM vm1 = VM.getVM(1);

    SerializableRunnable create = new CacheSerializableRunnable("Create Region") {
      @Override
      public void run2() throws CacheException {
        createRegion(name);
      }
    };

    vm0.invoke(create);
    vm1.invoke(create);

    vm0.invoke(new CacheSerializableRunnable("Create and populate") {
      @Override
      public void run2() throws CacheException {
        Region<Object, Object> region = getRootRegion().getSubregion(name);
        region.put(key, oldValue);
      }
    });
    vm1.invoke(new CacheSerializableRunnable("Define entry") {
      @Override
      public void run2() throws CacheException {
        Region<Object, Object> region = getRootRegion().getSubregion(name);
        if (!getRegionAttributes().getDataPolicy().withReplication()) {
          region.create(key, null);
        }
      }
    });
    vm0.invoke(new CacheSerializableRunnable("Update entry") {
      @Override
      public void run2() throws CacheException {
        Region<Object, Object> region = getRootRegion().getSubregion(name);
        region.put(key, newValue);
      }
    });
    vm1.invoke(repeatingIfNecessary(new CacheSerializableRunnable("Get entry") {
      @Override
      public void run2() throws CacheException {
        Region<Object, Object> region = getRootRegion().getSubregion(name);
        assertThat(region.get(key)).isEqualTo(newValue);
      }
    }));
  }


  /**
   * Tests that {@linkplain Region#destroy destroying} an entry is propagated to all VMs that define
   * that entry.
   */
  @Test
  public void testDistributedDestroy() {
    assertThat(getRegionAttributes().getScope().isDistributed()).isTrue();

    final String name = this.getUniqueName();

    SerializableRunnable create = new CacheSerializableRunnable("Create Region") {
      @Override
      public void run2() throws CacheException {
        Region<Object, Object> region = createRegion(name);
        assertThat(region.isDestroyed()).isFalse();
        Region root = region.getParentRegion();
        assertThat(root.isDestroyed()).isFalse();
      }
    };

    VM vm0 = VM.getVM(0);
    VM vm1 = VM.getVM(1);
    VM vm2 = VM.getVM(2);

    vm0.invoke(create);
    vm1.invoke(create);
    vm2.invoke(create);

    final Object key = "KEY";
    final Object value = "VALUE";

    SerializableRunnable put = new CacheSerializableRunnable("Put key/value") {
      @Override
      public void run2() throws CacheException {
        Region<Object, Object> region = getRootRegion().getSubregion(name);
        region.put(key, value);
        assertThat(region.isDestroyed()).isFalse();
        assertThat(region.getParentRegion().isDestroyed()).isFalse();
        flushIfNecessary(region);
      }
    };

    vm0.invoke(put);
    vm1.invoke(put);
    vm2.invoke(put);

    SerializableRunnable verifyPut = new CacheSerializableRunnable("Verify Put") {
      @Override
      public void run2() throws CacheException {
        Region<?, ?> root = getRootRegion();
        assertThat(root.isDestroyed()).isFalse();
        Region<Object, Object> region = root.getSubregion(name);
        assertThat(region.isDestroyed()).isFalse();
        assertThat(region.getEntry(key).getValue()).isEqualTo(value);
      }
    };

    vm0.invoke(verifyPut);
    vm1.invoke(verifyPut);
    vm2.invoke(verifyPut);

    vm0.invoke(new CacheSerializableRunnable("Destroy Entry") {
      @Override
      public void run2() throws CacheException {
        Region<?, ?> region = getRootRegion().getSubregion(name);
        region.destroy(key);
        flushIfNecessary(region);
      }
    });

    CacheSerializableRunnable verifyDestroy =
        new CacheSerializableRunnable("Verify entry destruction") {
          @Override
          public void run2() throws CacheException {
            Region<?, ?> root = getRootRegion();
            assertThat(root.isDestroyed()).isFalse();
            Region<Object, Object> region = root.getSubregion(name);
            assertThat(region.isDestroyed()).isFalse();
            assertThat(region.getEntry(key)).isNull();
          }
        };
    vm0.invoke(verifyDestroy);
    vm1.invoke(verifyDestroy);
    vm2.invoke(verifyDestroy);
  }

  /**
   * Tests that {@linkplain Region#destroy destroying} a region is propagated to all VMs that define
   * that region.
   */
  @Test
  public void testDistributedRegionDestroy() {
    assertThat(getRegionAttributes().getScope().isDistributed()).isTrue();

    final String name = this.getUniqueName();

    SerializableRunnable create = new CacheSerializableRunnable("Create Region") {
      @Override
      public void run2() throws CacheException {
        createRegion(name);
      }
    };

    invokeInEveryVM(create);

    VM vm0 = VM.getVM(0);

    vm0.invoke(new CacheSerializableRunnable("Destroy Region") {
      @Override
      public void run2() throws CacheException {
        Region<Object, Object> region = getRootRegion().getSubregion(name);
        region.destroyRegion();
        flushIfNecessary(region);
      }
    });

    invokeInEveryVM(new CacheSerializableRunnable("Verify region destruction") {
      @Override
      public void run2() throws CacheException {
        await()
            .until(() -> getRootRegion().getSubregion(name) == null);
      }
    });
  }

  /**
   * Tests that a {@linkplain Region#localDestroy} does not effect other VMs that define that
   * entry.
   */
  @Test
  public void testLocalDestroy() throws Exception {
    assumeThat(supportsLocalDestroyAndLocalInvalidate()).isTrue();

    // test not valid for persistBackup region since they have to be
    // mirrored KEYS_VALUES
    if (getRegionAttributes().getDataPolicy().withPersistence()) {
      return;
    }

    assertThat(getRegionAttributes().getScope().isDistributed()).isTrue();

    final String name = this.getUniqueName();

    SerializableRunnable create = new CacheSerializableRunnable("Create Region") {
      @Override
      public void run2() throws CacheException {
        createRegion(name);
      }
    };

    VM vm0 = VM.getVM(0);
    VM vm1 = VM.getVM(1);

    vm0.invoke(create);
    vm1.invoke(create);

    Thread.sleep(250);

    final Object key = "KEY";
    final Object value = "VALUE";

    SerializableRunnable put = new CacheSerializableRunnable("Put key/value") {
      @Override
      public void run2() throws CacheException {
        Region<Object, Object> region = getRootRegion().getSubregion(name);
        region.put(key, value);
      }
    };

    vm0.invoke(put);
    vm1.invoke(put);

    Thread.sleep(250);

    vm0.invoke(new CacheSerializableRunnable("Local Destroy Entry") {
      @Override
      public void run2() throws CacheException {
        Region<Object, Object> region = getRootRegion().getSubregion(name);
        region.localDestroy(key);
      }
    });

    Thread.sleep(250);

    SerializableRunnable verify = new CacheSerializableRunnable("Verify entry existence") {
      @Override
      public void run2() throws CacheException {
        Region<Object, Object> region = getRootRegion().getSubregion(name);
        assertThat(region.getEntry(key)).isNotNull();
      }
    };
    vm1.invoke(verify);
  }

  /**
   * Tests that a {@link Region#localDestroyRegion} is not propagated to other VMs that define that
   * region.
   */
  @Test
  public void testLocalRegionDestroy() throws Exception {
    assertThat(getRegionAttributes().getScope().isDistributed()).isTrue();

    final String name = this.getUniqueName();

    SerializableRunnable create = new CacheSerializableRunnable("Create Region") {
      @Override
      public void run2() throws CacheException {
        createRegion(name);
      }
    };

    VM vm0 = VM.getVM(0);
    VM vm1 = VM.getVM(1);

    vm0.invoke(create);
    vm1.invoke(create);

    Thread.sleep(250);

    vm0.invoke(new CacheSerializableRunnable("Local Destroy Region") {
      @Override
      public void run2() throws CacheException {
        getRootRegion().getSubregion(name).localDestroyRegion();
      }
    });

    Thread.sleep(250);

    SerializableRunnable verify = new CacheSerializableRunnable("Verify region existence") {
      @Override
      public void run2() throws CacheException {
        assertThat(getRootRegion().getSubregion(name)).isNotNull();
      }
    };
    vm1.invoke(verify);
  }

  /**
   * Tests that {@linkplain Region#invalidate invalidating} an entry is propagated to all VMs that
   * define that entry.
   */
  @Test
  public void testDistributedInvalidate() {
    assertThat(getRegionAttributes().getScope().isDistributed()).isTrue();

    final String name = this.getUniqueName();

    SerializableRunnable create = new CacheSerializableRunnable("Create Region") {
      @Override
      public void run2() throws CacheException {
        createRegion(name);
      }
    };

    VM vm0 = VM.getVM(0);
    VM vm1 = VM.getVM(1);
    VM vm2 = VM.getVM(2);

    vm0.invoke(create);
    vm1.invoke(create);

    // vm2 is on a different gemfire system
    vm2.invoke(create);

    final Object key = "KEY";
    final Object value = "VALUE";

    SerializableRunnable put = new CacheSerializableRunnable("Put key/value") {
      @Override
      public void run2() throws CacheException {
        Region<Object, Object> region = getRootRegion().getSubregion(name);
        region.put(key, value);
        flushIfNecessary(region);
      }
    };

    vm0.invoke(put);
    vm1.invoke(put);
    vm2.invoke(put);

    vm0.invoke(new CacheSerializableRunnable("Invalidate Entry") {
      @Override
      public void run2() throws CacheException {
        Region<Object, Object> region = getRootRegion().getSubregion(name);
        region.invalidate(key);
        flushIfNecessary(region);
      }
    });

    CacheSerializableRunnable verify = new CacheSerializableRunnable("Verify entry invalidation") {
      @Override
      public void run2() throws CacheException {
        Region<Object, Object> region = getRootRegion().getSubregion(name);
        Region.Entry entry = region.getEntry(key);
        assertThat(entry).isNotNull();
        if (entry.getValue() != null) {
          // changed from severe to fine because it is possible
          // for this to return non-null on d-no-ack
          // that is was invokeRepeatingIfNecessary is called
          logger.debug("invalidated entry has value of " + entry.getValue());
        }
        assertThat(entry.getValue()).isNull();
      }
    };

    vm1.invoke(verify);
    vm2.invoke(verify);
  }

  /**
   * Tests that {@linkplain Region#invalidate invalidating} an entry in multiple VMs does not cause
   * any problems.
   */
  @Test
  public void testDistributedInvalidate4() {
    assertThat(getRegionAttributes().getScope().isDistributed()).isTrue();

    final String name = this.getUniqueName();
    final Object key = "KEY";
    final Object value = "VALUE";

    SerializableRunnable create = new CacheSerializableRunnable("Create Region") {
      @Override
      public void run2() throws CacheException {
        createRegion(name);
      }
    };

    int vmCount = VM.getVMCount();
    for (int i = 0; i < vmCount; i++) {
      VM vm0 = VM.getVM(i);
      vm0.invoke(create);
    }

    SerializableRunnable put = new CacheSerializableRunnable("put entry") {
      @Override
      public void run2() throws CacheException {
        Region<Object, Object> region = getRootRegion().getSubregion(name);
        region.put(key, value);
        flushIfNecessary(region);
      }
    };

    for (int i = 0; i < vmCount; i++) {
      VM vm = VM.getVM(i);
      vm.invoke(put);
    }

    SerializableRunnable invalidate = new CacheSerializableRunnable("Invalidate Entry") {
      @Override
      public void run2() throws CacheException {
        Region<Object, Object> region = getRootRegion().getSubregion(name);
        region.invalidate(key);
        flushIfNecessary(region);
      }
    };

    for (int i = 0; i < vmCount; i++) {
      VM vm = VM.getVM(i);
      vm.invoke(invalidate);
    }

    SerializableRunnable verify = new CacheSerializableRunnable("Verify entry invalidation") {
      @Override
      public void run2() throws CacheException {
        Region<Object, Object> region = getRootRegion().getSubregion(name);
        Region.Entry entry = region.getEntry(key);
        assertThat(entry).isNotNull();
        assertThat(entry.getValue()).isNull();
      }
    };

    for (int i = 0; i < vmCount; i++) {
      VM vm0 = VM.getVM(i);
      vm0.invoke(verify);
    }
  }

  /**
   * Tests that {@linkplain Region#invalidateRegion invalidating} a region is propagated to all VMs
   * that define that entry.
   */
  @Test
  public void testDistributedRegionInvalidate() {
    assumeThat(supportsSubregions()).isTrue();

    final String name = this.getUniqueName();
    final String subname = "sub";
    final boolean useSubs = getRegionAttributes().getPartitionAttributes() == null;

    SerializableRunnable create = new CacheSerializableRunnable("Create Region") {
      @Override
      public void run2() throws CacheException {
        Region region;
        region = createRegion(name);
        if (useSubs) {
          region.createSubregion(subname, region.getAttributes());
        }
      }
    };

    invokeInEveryVM(create);

    final Object key = "KEY";
    final Object value = "VALUE";
    final Object key2 = "KEY2";
    final Object value2 = "VALUE2";

    SerializableRunnable put = new CacheSerializableRunnable("Put key/value") {
      @Override
      public void run2() throws CacheException {
        Region<Object, Object> region = getRootRegion().getSubregion(name);
        region.put(key, value);
        region.put(key2, value2);
        flushIfNecessary(region);

        if (useSubs) {
          Region<Object, Object> subregion = region.getSubregion(subname);
          subregion.put(key, value);
          subregion.put(key2, value2);
          flushIfNecessary(subregion);
        }
      }
    };

    invokeInEveryVM(put);

    final VM vm0 = VM.getVM(0);

    vm0.invoke(new CacheSerializableRunnable("Invalidate Region") {
      @Override
      public void run2() throws CacheException {
        Region<Object, Object> region = getRootRegion().getSubregion(name);
        region.invalidateRegion();
      }
    });

    CacheSerializableRunnable verify = new CacheSerializableRunnable("Verify region invalidation") {
      @Override
      public void run2() {
        Region<Object, Object> region = getRootRegion().getSubregion(name);
        Region.Entry<Object, Object> entry = region.getEntry(key);
        assertThat(entry).isNotNull();
        Object v = entry.getValue();
        assertThat(v).isNull();

        entry = region.getEntry(key2);
        assertThat(entry).isNotNull();
        assertThat(entry.getValue()).isNull();

        if (useSubs) {
          Region<Object, Object> subregion = region.getSubregion(subname);
          entry = subregion.getEntry(key);
          assertThat(entry).isNotNull();
          assertThat(entry.getValue()).isNull();

          entry = subregion.getEntry(key2);
          assertThat(entry).isNotNull();
          assertThat(entry.getValue()).isNull();
        }
      }
    };

    invokeInEveryVM(repeatingIfNecessary(verify));
  }

  /**
   * Tests that a {@link CacheListener} is invoked in a remote VM.
   */
  @Test
  public void testRemoteCacheListener() {
    assertThat(getRegionAttributes().getScope().isDistributed()).isTrue();

    final String name = this.getUniqueName();
    final Object key = "KEY";
    final Object oldValue = "OLD_VALUE";
    final Object newValue = "NEW_VALUE";
    // final Object key2 = "KEY2";
    // final Object value2 = "VALUE2";

    SerializableRunnable populate = new CacheSerializableRunnable("Create Region and Put") {
      @Override
      public void run2() throws CacheException {
        Region<Object, Object> region = createRegion(name);
        region.put(key, oldValue);
      }
    };

    final VM vm0 = VM.getVM(0);
    final VM vm1 = VM.getVM(1);

    vm0.invoke(populate);
    vm1.invoke(populate);

    vm1.invoke(new CacheSerializableRunnable("Set listener") {
      @Override
      public void run2() throws CacheException {
        final Region<Object, Object> region = getRootRegion().getSubregion(name);
        setListener(new TestCacheListener<Object, Object>() {
          @Override
          public void afterUpdate2(EntryEvent<Object, Object> event) {
            assertThat(event.getOperation()).isEqualTo(Operation.UPDATE);
            assertThat(event.getRegion()).isEqualTo(region);
            assertThat(event.getOperation().isDistributed()).isTrue();
            assertThat(event.getOperation().isExpiration()).isFalse();
            assertThat(event.isOriginRemote()).isTrue();
            assertThat(event.getDistributedMember()).isEqualTo(event.getCallbackArgument());
            assertThat(event.getKey()).isEqualTo(key);
            assertThat(event.getOldValue()).isEqualTo(oldValue);
            assertThat(event.getNewValue()).isEqualTo(newValue);
            assertThat(event.getOperation().isLoad()).isFalse();
            assertThat(event.getOperation().isLocalLoad()).isFalse();
            assertThat(event.getOperation().isNetLoad()).isFalse();
            assertThat(event.getOperation().isNetSearch()).isFalse();
            if (event.getRegion().getAttributes().getOffHeap()) {
              // since off heap always serializes the old value is serialized and available
              assertThat(event.getSerializedOldValue().getDeserializedValue()).isEqualTo(oldValue);
            } else {
              assertThat(event.getSerializedOldValue()).isNull(); // since it was put originally in
              // this VM
            }
            DataInputStream dis = new DataInputStream(
                new ByteArrayInputStream(event.getSerializedNewValue().getSerializedValue()));
            try {
              assertThat(DataSerializer.<Object>readObject(dis)).isEqualTo(newValue);
            } catch (Exception e) {
              fail("Unexpected Exception", e);
            }
          }
        });
        region.getAttributesMutator().addCacheListener(listener());
      }
    });

    // I see no reason to pause here.
    // The test used to pause here but only if no-ack.
    // But we have no operations to wait for.
    // The last thing we did was install a listener in vm1
    // and it is possible that vm0 does not yet know we have
    // a listener but for this test it does not matter.
    // So I'm commenting out the following pause:
    // pauseIfNecessary();
    // If needed then do a flushIfNecessary(region) after adding the cache listener

    vm0.invoke(new CacheSerializableRunnable("Update") {
      @Override
      public void run2() throws CacheException {
        Region<Object, Object> region = getRootRegion().getSubregion(name);
        region.put(key, newValue, getSystem().getDistributedMember());
      }
    });

    vm1.invoke(new CacheSerializableRunnable("Verify Update") {
      @Override
      public void run2() throws CacheException {
        listener().waitForInvocation(3000, 10);

        // Setup listener for next test
        final Region<Object, Object> region = getRootRegion().getSubregion(name);
        setListener(new TestCacheListener<Object, Object>() {
          @Override
          public void afterInvalidate2(EntryEvent<Object, Object> event) {
            assertThat(event.getOperation()).isEqualTo(Operation.INVALIDATE);
            assertThat(event.getRegion()).isEqualTo(region);
            assertThat(event.getOperation().isDistributed()).isTrue();
            assertThat(event.getOperation().isExpiration()).isFalse();
            assertThat(event.isOriginRemote()).isTrue();
            assertThat(event.getDistributedMember()).isEqualTo(event.getCallbackArgument());
            assertThat(event.getKey()).isEqualTo(key);
            assertThat(event.getOldValue()).isEqualTo(newValue);
            assertThat(event.getNewValue()).isNull();
            assertThat(event.getOperation().isLoad()).isFalse();
            assertThat(event.getOperation().isLocalLoad()).isFalse();
            assertThat(event.getOperation().isNetLoad()).isFalse();
            assertThat(event.getOperation().isNetSearch()).isFalse();
            assertThat(event.getSerializedNewValue()).isNull();
            DataInputStream dis = new DataInputStream(
                new ByteArrayInputStream(event.getSerializedOldValue().getSerializedValue()));
            try {
              assertThat(DataSerializer.<Object>readObject(dis)).isEqualTo(newValue);
            } catch (Exception e) {
              fail("Unexpected Exception", e);
            }
          }
        });
        region.getAttributesMutator().addCacheListener(listener());
      }
    });

    vm0.invoke(new CacheSerializableRunnable("Invalidate") {
      @Override
      public void run2() throws CacheException {
        Region<Object, Object> region = getRootRegion().getSubregion(name);
        region.invalidate(key, getSystem().getDistributedMember());
      }
    });

    vm1.invoke(new CacheSerializableRunnable("Verify Invalidate") {
      @Override
      public void run2() throws CacheException {
        listener().waitForInvocation(3000, 10);

        // Setup listener for next test
        final Region<Object, Object> region = getRootRegion().getSubregion(name);
        setListener(new TestCacheListener<Object, Object>() {
          @Override
          public void afterDestroy2(EntryEvent<Object, Object> event) {
            assertThat(event.getOperation().isDestroy()).isTrue();
            assertThat(event.getRegion()).isEqualTo(region);
            assertThat(event.getOperation().isDistributed()).isTrue();
            assertThat(event.getOperation().isExpiration()).isFalse();
            assertThat(event.isOriginRemote()).isTrue();
            assertThat(event.getDistributedMember()).isEqualTo(event.getCallbackArgument());
            assertThat(event.getKey()).isEqualTo(key);
            assertThat(event.getOldValue()).isNull();
            assertThat(event.getNewValue()).isNull();
            assertThat(event.getOperation().isLoad()).isFalse();
            assertThat(event.getOperation().isLocalLoad()).isFalse();
            assertThat(event.getOperation().isNetLoad()).isFalse();
            assertThat(event.getOperation().isNetSearch()).isFalse();
            assertThat(event.getSerializedOldValue()).isNull();
            assertThat(event.getSerializedNewValue()).isNull();
          }
        });
        region.getAttributesMutator().addCacheListener(listener());
      }
    });

    vm0.invoke(new CacheSerializableRunnable("Destroy") {
      @Override
      public void run2() throws CacheException {
        Region<Object, Object> region = getRootRegion().getSubregion(name);
        region.destroy(key, getSystem().getDistributedMember());
      }
    });

    vm1.invoke(new CacheSerializableRunnable("Verify Destroy") {
      @Override
      public void run2() throws CacheException {
        listener().waitForInvocation(3000, 10);

        // Setup listener for next test
        final Region<Object, Object> region = getRootRegion().getSubregion(name);
        setListener(new TestCacheListener<Object, Object>() {
          @Override
          public void afterRegionInvalidate2(RegionEvent<Object, Object> event) {
            assertThat(event.getOperation()).isEqualTo(Operation.REGION_INVALIDATE);
            assertThat(event.getRegion()).isEqualTo(region);
            assertThat(event.getOperation().isDistributed()).isTrue();
            assertThat(event.getOperation().isExpiration()).isFalse();
            assertThat(event.isOriginRemote()).isTrue();
            assertThat(event.getDistributedMember()).isEqualTo(event.getCallbackArgument());
          }
        });
        region.getAttributesMutator().addCacheListener(listener());
      }
    });

    vm0.invoke(new CacheSerializableRunnable("Invalidate Region") {
      @Override
      public void run2() throws CacheException {
        Region<Object, Object> region = getRootRegion().getSubregion(name);
        region.invalidateRegion(getSystem().getDistributedMember());
      }
    });

    vm1.invoke(new CacheSerializableRunnable("Verify Invalidate Region") {
      @Override
      public void run2() throws CacheException {
        listener().waitForInvocation(3000, 10);

        // Setup listener for next test
        final Region<Object, Object> region = getRootRegion().getSubregion(name);
        setListener(new TestCacheListener<Object, Object>() {
          @Override
          public void afterRegionDestroy2(RegionEvent<Object, Object> event) {
            assertThat(event.getOperation()).isEqualTo(Operation.REGION_DESTROY);
            assertThat(event.getRegion()).isEqualTo(region);
            assertThat(event.getOperation().isDistributed()).isTrue();
            assertThat(event.getOperation().isExpiration()).isFalse();
            assertThat(event.isOriginRemote()).isTrue();
            assertThat(event.getDistributedMember()).isEqualTo(event.getCallbackArgument());
          }
        });
        region.getAttributesMutator().addCacheListener(listener());
      }
    });

    vm0.invoke(new CacheSerializableRunnable("Destroy Region") {
      @Override
      public void run2() throws CacheException {
        Region<Object, Object> region = getRootRegion().getSubregion(name);
        region.destroyRegion(getSystem().getDistributedMember());
      }
    });

    vm1.invoke(new CacheSerializableRunnable("Verify Destroy Region") {
      @Override
      public void run2() throws CacheException {
        listener().waitForInvocation(3000, 10);
      }
    });
  }

  /**
   * Tests that a {@link CacheListener} is invoked in a remote VM.
   */
  @Test
  public void testRemoteCacheListenerInSubregion() {
    assumeThat(supportsSubregions()).isTrue();

    assertThat(getRegionAttributes().getScope().isDistributed()).isTrue();

    final String name = this.getUniqueName();

    SerializableRunnable create = new CacheSerializableRunnable("Create Region") {
      @Override
      public void run2() throws CacheException {
        createRegion(name);
      }
    };

    final VM vm0 = VM.getVM(0);
    final VM vm1 = VM.getVM(1);

    vm0.invoke(new CacheSerializableRunnable("Create Root") {
      @Override
      public void run2() throws CacheException {
        createRootRegion();
      }
    });

    vm1.invoke(create);

    vm1.invoke(new CacheSerializableRunnable("Set listener") {
      @Override
      public void run2() throws CacheException {
        final Region<Object, Object> region = getRootRegion().getSubregion(name);
        setListener(new TestCacheListener<Object, Object>() {
          @Override
          public void afterRegionInvalidate2(RegionEvent<Object, Object> event) {
            assertThat(event.getOperation()).isEqualTo(Operation.REGION_INVALIDATE);
            assertThat(event.getRegion()).isEqualTo(region);
            assertThat(event.getOperation().isDistributed()).isTrue();
            assertThat(event.getOperation().isExpiration()).isFalse();
            assertThat(event.isOriginRemote()).isTrue();
            assertThat(event.getDistributedMember()).isEqualTo(event.getCallbackArgument());
          }
        });
        region.getAttributesMutator().addCacheListener(listener());
      }
    });

    vm0.invoke(new CacheSerializableRunnable("Invalidate Root Region") {
      @Override
      public void run2() throws CacheException {
        getRootRegion().invalidateRegion(getSystem().getDistributedMember());
      }
    });

    vm1.invoke(new CacheSerializableRunnable("Verify Invalidate Region") {
      @Override
      public void run2() throws CacheException {
        listener().waitForInvocation(3000, 10);

        // Setup listener for next test
        final Region<Object, Object> region = getRootRegion().getSubregion(name);
        setListener(new TestCacheListener<Object, Object>() {
          @Override
          public void afterRegionDestroy2(RegionEvent<Object, Object> event) {
            assertThat(event.getOperation()).isEqualTo(Operation.REGION_DESTROY);
            assertThat(event.getRegion()).isEqualTo(region);
            assertThat(event.getOperation().isDistributed()).isTrue();
            assertThat(event.getOperation().isExpiration()).isFalse();
            assertThat(event.isOriginRemote()).isTrue();
            assertThat(event.getDistributedMember()).isEqualTo(event.getCallbackArgument());
          }
        });
        region.getAttributesMutator().addCacheListener(listener());
      }
    });

    vm0.invoke(new CacheSerializableRunnable("Destroy Root Region") {
      @Override
      public void run2() throws CacheException {
        getRootRegion().destroyRegion(getSystem().getDistributedMember());
      }
    });

    vm1.invoke(new CacheSerializableRunnable("Verify Destroy Region") {
      @Override
      public void run2() throws CacheException {
        listener().waitForInvocation(3000, 10);
      }
    });
  }


  /**
   * Indicate whether this region supports netload
   *
   * @return true if it supports netload
   */
  protected boolean supportsNetLoad() {
    return true;
  }

  /**
   * Tests that a {@link CacheLoader} is invoked in a remote VM. This essentially tests
   * <code>netLoad</code>.
   */
  @Test
  public void testRemoteCacheLoader() {
    assumeThat(supportsNetLoad()).isTrue();

    assertThat(getRegionAttributes().getScope().isDistributed()).isTrue();

    final String name = this.getUniqueName();
    final Object key = "KEY";
    final Object value = "VALUE";

    SerializableRunnable create = new CacheSerializableRunnable("Create Region") {
      @Override
      public void run2() throws CacheException {
        createRegion(name);
      }
    };

    final VM vm0 = VM.getVM(0);
    final VM vm1 = VM.getVM(1);

    vm0.invoke(create);
    vm1.invoke(create);

    vm1.invoke(new CacheSerializableRunnable("Set CacheLoader") {
      @Override
      public void run2() throws CacheException {
        final Region<Object, Object> region = getRootRegion().getSubregion(name);
        setLoader(new TestCacheLoader<Object, Object>() {
          @Override
          public Object load2(LoaderHelper<Object, Object> helper) throws CacheLoaderException {
            assertThat(helper.getRegion()).isEqualTo(region);
            assertThat(helper.getKey()).isEqualTo(key);
            assertThat(helper.getArgument()).isNull();

            return value;
          }
        });
        region.getAttributesMutator().setCacheLoader(loader());
      }
    });

    vm0.invoke(new CacheSerializableRunnable("Remote load") {
      @Override
      public void run2() throws CacheException {
        Region<Object, Object> region = getRootRegion().getSubregion(name);
        assertThat(region.get(key)).isEqualTo(value);
      }
    });

    vm1.invoke(new SerializableRunnable("Verify loader") {
      @Override
      public void run() {
        assertThat(loader().wasInvoked()).isTrue();
      }
    });
  }

  /**
   * Tests that the parameter passed to a remote {@link CacheLoader} is actually passed.
   */
  @Test
  public void testRemoteCacheLoaderArg() {
    assumeThat(supportsNetLoad()).isTrue();

    assertThat(getRegionAttributes().getScope().isDistributed()).isTrue();

    final String name = this.getUniqueName();
    final Object key = "KEY";
    final Object value = "VALUE";
    final String arg = "ARG";

    SerializableRunnable create = new CacheSerializableRunnable("Create Region") {
      @Override
      public void run2() throws CacheException {
        createRegion(name);
        // Can't test non-Serializable callback argument here
        // because netLoad will not occur because there are no
        // other members with the region defined when it is
        // created. Hooray for intelligent messaging.
      }
    };

    final VM vm0 = VM.getVM(0);
    final VM vm1 = VM.getVM(1);

    vm0.invoke(create);
    vm1.invoke(create);

    vm1.invoke(new CacheSerializableRunnable("Set CacheLoader") {
      @Override
      public void run2() throws CacheException {
        final Region<Object, Object> region = getRootRegion().getSubregion(name);
        setLoader(new TestCacheLoader<Object, Object>() {
          @Override
          public Object load2(LoaderHelper<Object, Object> helper) throws CacheLoaderException {
            assertThat(helper.getRegion()).isEqualTo(region);
            assertThat(helper.getKey()).isEqualTo(key);
            assertThat(helper.getArgument()).isEqualTo(arg);

            return value;
          }
        });
        region.getAttributesMutator().setCacheLoader(loader());
        flushIfNecessary(region);
      }
    });

    vm0.invoke(new CacheSerializableRunnable("Remote load") {
      @Override
      public void run2() throws CacheException {
        Region<Object, Object> region = getRootRegion().getSubregion(name);

        try {
          // Use a non-serializable arg object
          region.get(key, new Object() {});
          fail("Should have thrown an IllegalArgumentException");

        } catch (IllegalArgumentException ex) {
          // pass...
        }
        assertThat(region.getEntry(key)).isNull();
        try {
          assertThat(region.get(key, arg)).isEqualTo(value);
        } catch (IllegalArgumentException ignored) {
        }
      }
    });

    vm1.invoke(new SerializableRunnable("Verify loader") {
      @Override
      public void run() {
        assertThat(loader().wasInvoked()).isTrue();
      }
    });
  }

  /**
   * Tests that a remote {@link CacheLoader} that throws a {@link CacheLoaderException} results is
   * propagated back to the caller.
   */
  @Test
  public void testRemoteCacheLoaderException() {
    assumeThat(supportsNetLoad()).isTrue();

    assertThat(getRegionAttributes().getScope().isDistributed()).isTrue();

    final String name = this.getUniqueName();
    final Object key = "KEY";

    SerializableRunnable create = new CacheSerializableRunnable("Create Region") {
      @Override
      public void run2() throws CacheException {
        createRegion(name);
      }
    };

    final VM vm0 = VM.getVM(0);
    final VM vm1 = VM.getVM(1);

    vm0.invoke(create);
    vm1.invoke(create);

    vm1.invoke(new CacheSerializableRunnable("Set CacheLoader") {
      @Override
      public void run2() throws CacheException {
        final Region<Object, Object> region = getRootRegion().getSubregion(name);
        setLoader(new TestCacheLoader<Object, Object>() {
          @Override
          public Object load2(LoaderHelper<Object, Object> helper) throws CacheLoaderException {
            assertThat(helper.getRegion()).isEqualTo(region);
            assertThat(helper.getKey()).isEqualTo(key);
            assertThat(helper.getArgument()).isNull();

            String s = "Test Exception";
            throw new CacheLoaderException(s);
          }
        });
        region.getAttributesMutator().setCacheLoader(loader());
        flushIfNecessary(region);
      }
    });

    vm0.invoke(new CacheSerializableRunnable("Remote load") {
      @Override
      public void run2() throws CacheException {
        Region<Object, Object> region = getRootRegion().getSubregion(name);
        try {
          region.get(key);
          fail("Should have thrown a CacheLoaderException");

        } catch (CacheLoaderException ex) {
          // pass...
        }
      }
    });

    vm1.invoke(new SerializableRunnable("Verify loader") {
      @Override
      public void run() {
        assertThat(loader().wasInvoked()).isTrue();
      }
    });
  }

  @Test
  public void testCacheLoaderWithNetSearch() {
    assumeThat(supportsNetLoad()).isTrue();

    // some tests use mirroring by default (e.g. persistBackup regions)
    // if so, then this test won't work right
    assumeThat(getRegionAttributes().getDataPolicy().withReplication()).isFalse();
    assumeThat(getRegionAttributes().getDataPolicy().withPreloaded()).isFalse();

    final String name = this.getUniqueName();
    final Object key = this.getUniqueName();
    final Object value = 42;

    // use vm on other gemfire system
    VM vm1 = VM.getVM(1);
    vm1.invoke(new CacheSerializableRunnable("set remote value") {
      @Override
      public void run2() throws CacheException {
        Region<Object, Object> rgn = createRegion(name);
        rgn.put(key, value);
        flushIfNecessary(rgn);
      }
    });

    final TestCacheLoader<Object, Object> loader1 = new TestCacheLoader<Object, Object>() {
      @Override
      public Object load2(LoaderHelper<Object, Object> helper) throws CacheLoaderException {

        assertThat(helper.getKey()).isEqualTo(key);
        assertThat(helper.getRegion().getName()).isEqualTo(name);

        try {
          helper.getRegion().getAttributes();
          Object result = helper.netSearch(false);
          assertThat(result).isEqualTo(value);
          return result;
        } catch (TimeoutException ex) {
          fail("Why did I time out?", ex);
        }
        return null;
      }
    };

    AttributesFactory<Object, Object> f = new AttributesFactory<>(getRegionAttributes());
    f.setCacheLoader(loader1);
    Region<Object, Object> region = createRegion(name, f.create());

    loader1.wasInvoked();

    Region.Entry entry = region.getEntry(key);
    assertThat(entry).isNull();
    region.create(key, null);

    entry = region.getEntry(key);
    assertThat(entry).isNotNull();
    assertThat(entry.getValue()).isNull();

    // make sure value is still there in vm1
    vm1.invoke(new CacheSerializableRunnable("verify remote value") {
      @Override
      public void run2() throws CacheException {
        Region rgn = getRootRegion().getSubregion(name);
        assertThat(rgn.getEntry(key).getValue()).isEqualTo(value);
      }
    });

    assertThat(region.get(key)).isEqualTo(value);
    // if global scope, then a netSearch is done BEFORE the loader is invoked,
    // so we get the value but the loader is never invoked.
    if (region.getAttributes().getScope().isGlobal()) {
      assertThat(loader1.wasInvoked()).isFalse();
    } else {
      assertThat(loader1.wasInvoked()).isTrue();
    }
    assertThat(region.getEntry(key).getValue()).isEqualTo(value);
  }

  @Test
  public void testCacheLoaderWithNetLoad() {
    // replicated regions and partitioned regions make no sense for this
    // test
    assumeThat(getRegionAttributes().getDataPolicy().withReplication()).isFalse();
    assumeThat(getRegionAttributes().getDataPolicy().withPreloaded()).isFalse();
    assumeThat(getRegionAttributes().getPartitionAttributes())
        .withFailMessage("the region has partition attributes").isNull();

    final String name = this.getUniqueName();
    final Object key = this.getUniqueName();
    final Object value = 42;

    final VM vm1 = VM.getVM(1);
    vm1.invoke(new CacheSerializableRunnable("set up remote loader") {
      @Override
      public void run2() throws CacheException {
        final TestCacheLoader<Object, Object> remoteloader = new TestCacheLoader<Object, Object>() {
          @Override
          public Object load2(LoaderHelper<Object, Object> helper) throws CacheLoaderException {
            assertThat(helper.getKey()).isEqualTo(key);
            assertThat(helper.getRegion().getName()).isEqualTo(name);
            return value;
          }
        };

        AttributesFactory<Object, Object> factory = new AttributesFactory<>(getRegionAttributes());
        factory.setCacheLoader(remoteloader);
        createRegion(name, factory.create());
      }
    });

    final TestCacheLoader<Object, Object> loader1 = new TestCacheLoader<Object, Object>() {
      @Override
      public Object load2(LoaderHelper<Object, Object> helper) throws CacheLoaderException {

        assertThat(helper.getKey()).isEqualTo(key);
        assertThat(helper.getRegion().getName()).isEqualTo(name);

        try {
          helper.getRegion().getAttributes();
          Object result = helper.netSearch(true);
          assertThat(result).isEqualTo(value);
          return result;
        } catch (TimeoutException ex) {
          fail("Why did I time out?", ex);
        }
        return null;
      }
    };

    AttributesFactory<Object, Object> f = new AttributesFactory<>(getRegionAttributes());
    f.setCacheLoader(loader1);
    Region<Object, Object> region = createRegion(name, f.create());

    loader1.wasInvoked();

    Region.Entry entry = region.getEntry(key);
    assertThat(entry).isNull();

    region.create(key, null);

    entry = region.getEntry(key);
    assertThat(entry).isNotNull();
    assertThat(entry.getValue()).isNull();

    assertThat(region.get(key)).isEqualTo(value);

    assertThat(loader1.wasInvoked()).isTrue();
    assertThat(region.getEntry(key).getValue()).isEqualTo(value);
  }


  /**
   * Tests that {@link Region#get} returns <code>null</code> when there is no remote loader.
   */
  @Test
  public void testNoRemoteCacheLoader() {
    assertThat(getRegionAttributes().getScope().isDistributed()).isTrue();

    final String name = this.getUniqueName();
    final Object key = "KEY";

    SerializableRunnable create = new CacheSerializableRunnable("Create Region") {
      @Override
      public void run2() throws CacheException {
        createRegion(name);
      }
    };
    final VM vm0 = VM.getVM(0);
    final VM vm1 = VM.getVM(1);

    vm0.invoke(create);
    vm1.invoke(create);

    vm0.invoke(new CacheSerializableRunnable("Remote load") {
      @Override
      public void run2() throws CacheException {
        Region<Object, Object> region = getRootRegion().getSubregion(name);
        assertThat(region.get(key)).isNull();
      }
    });
  }

  /**
   * Tests that a remote <code>CacheLoader</code> is not invoked if the remote region has an invalid
   * entry (that is, a key, but no value).
   */
  @Test
  public void testNoLoaderWithInvalidEntry() {
    assumeThat(supportsNetLoad()).isTrue();

    final String name = this.getUniqueName();
    final Object key = "KEY";
    final Object value = "VALUE";

    SerializableRunnable create = new CacheSerializableRunnable("Create Region") {
      @Override
      public void run2() throws CacheException {
        Region<Object, Object> region = createRegion(name);
        setLoader(new TestCacheLoader<Object, Object>() {
          @Override
          public Object load2(LoaderHelper<Object, Object> helper) throws CacheLoaderException {

            return value;
          }
        });
        region.getAttributesMutator().setCacheLoader(loader());
      }
    };

    final VM vm0 = VM.getVM(0);
    final VM vm1 = VM.getVM(1);

    vm0.invoke(create);
    vm1.invoke(create);

    vm1.invoke(new CacheSerializableRunnable("Create invalid entry") {
      @Override
      public void run2() throws CacheException {
        Region<Object, Object> region = getRootRegion().getSubregion(name);
        region.create(key, null);
      }
    });

    vm0.invoke(new CacheSerializableRunnable("Remote get") {
      @Override
      public void run2() throws CacheException {
        Region<Object, Object> region = getRootRegion().getSubregion(name);
        assertThat(region.get(key)).isEqualTo(value);
        assertThat(loader().wasInvoked()).isTrue();
      }
    });

    vm1.invoke(new SerializableRunnable("Verify loader") {
      @Override
      public void run() {
        assertThat(loader().wasInvoked()).isFalse();
      }
    });
  }

  /**
   * Tests that a remote {@link CacheWriter} is invoked and that <code>CacheWriter</code> arguments
   * and {@link CacheWriterException}s are propagated appropriately.
   */
  @Test
  public void testRemoteCacheWriter() {
    assertThat(getRegionAttributes().getScope().isDistributed()).isTrue();

    final String name = this.getUniqueName();
    final Object key = "KEY";
    final Object oldValue = "OLD_VALUE";
    final Object newValue = "NEW_VALUE";
    final Object arg = "ARG";
    final Object exception = "EXCEPTION";

    final Object key2 = "KEY2";
    final Object value2 = "VALUE2";

    SerializableRunnable create = new CacheSerializableRunnable("Create Region") {
      @Override
      public void run2() throws CacheException {
        Region<Object, Object> region = createRegion(name);

        // Put key2 in the region before any callbacks are
        // registered, so it can be destroyed later
        region.put(key2, value2);
        assertThat(region.size()).isEqualTo(1);
        if (region.getAttributes().getOffHeap() && !(region instanceof PartitionedRegion)) {
          GemFireCacheImpl gfc = (GemFireCacheImpl) getCache();
          MemoryAllocatorImpl ma = (MemoryAllocatorImpl) gfc.getOffHeapStore();
          LocalRegion reRegion;
          reRegion = (LocalRegion) region;
          RegionEntry re = reRegion.getRegionEntry(key2);
          StoredObject so = (StoredObject) re.getValue();
          assertThat(so.getRefCount()).isEqualTo(1);
          assertThat(ma.getStats().getObjects()).isEqualTo(1);
        }
      }
    };

    final VM vm0 = VM.getVM(0);
    final VM vm1 = VM.getVM(1);

    vm0.invoke(create);
    vm1.invoke(create);

    //////// Create

    vm1.invoke(new CacheSerializableRunnable("Set Writer") {
      @Override
      public void run2() throws CacheException {
        final Region<Object, Object> region = getRootRegion().getSubregion(name);
        setWriter(new TestCacheWriter<Object, Object>() {
          @Override
          public void beforeCreate2(EntryEvent<Object, Object> event) throws CacheWriterException {

            if (exception.equals(event.getCallbackArgument())) {
              String s = "Test Exception";
              throw new CacheWriterException(s);
            }

            assertThat(event.getRegion()).isEqualTo(region);
            assertThat(event.getOperation().isCreate()).isTrue();
            assertThat(event.getOperation().isDistributed()).isTrue();
            assertThat(event.getOperation().isExpiration()).isFalse();
            assertThat(event.isOriginRemote()).isTrue();
            assertThat(event.getKey()).isEqualTo(key);
            assertThat(event.getOldValue()).isNull();
            assertThat(event.getNewValue()).isEqualTo(oldValue);
            assertThat(event.getOperation().isLoad()).isFalse();
            assertThat(event.getOperation().isLocalLoad()).isFalse();
            assertThat(event.getOperation().isNetLoad()).isFalse();
            assertThat(event.getOperation().isNetSearch()).isFalse();

          }
        });
        region.getAttributesMutator().setCacheWriter(writer());
        flushIfNecessary(region);
      }
    });

    vm0.invoke(new CacheSerializableRunnable("Create with Exception") {
      @Override
      public void run2() throws CacheException {
        Region<Object, Object> region = getRootRegion().getSubregion(name);
        try {
          region.put(key, oldValue, exception);
          fail("Should have thrown a CacheWriterException");

        } catch (CacheWriterException ex) {
          assertThat(region.getEntry(key)).isNull();
          assertThat(region.size()).isEqualTo(1);
          if (region.getAttributes().getOffHeap() && !(region instanceof PartitionedRegion)) {
            GemFireCacheImpl gfc = (GemFireCacheImpl) getCache();
            MemoryAllocatorImpl ma = (MemoryAllocatorImpl) gfc.getOffHeapStore();
            assertThat(ma.getStats().getObjects()).isEqualTo(1);
          }
        }
      }
    });

    vm1.invoke(new SerializableRunnable("Verify callback") {
      @Override
      public void run() {
        assertThat(writer().wasInvoked()).isTrue();
      }
    });

    vm0.invoke(new CacheSerializableRunnable("Create with Argument") {
      @Override
      public void run2() throws CacheException {
        Region<Object, Object> region = getRootRegion().getSubregion(name);
        region.put(key, oldValue, arg);
        assertThat(region.size()).isEqualTo(2);
        if (region.getAttributes().getOffHeap() && !(region instanceof PartitionedRegion)) {
          GemFireCacheImpl gfc = (GemFireCacheImpl) getCache();
          MemoryAllocatorImpl ma = (MemoryAllocatorImpl) gfc.getOffHeapStore();
          assertThat(ma.getStats().getObjects()).isEqualTo(2);
          LocalRegion reRegion;
          reRegion = (LocalRegion) region;
          StoredObject so = (StoredObject) reRegion.getRegionEntry(key).getValue();
          assertThat(so.getRefCount()).isEqualTo(1);
        }
      }
    });
    vm1.invoke(new SerializableRunnable("Verify callback") {
      @Override
      public void run() {
        assertThat(writer().wasInvoked()).isTrue();
      }
    });

    //////// Update

    vm1.invoke(new CacheSerializableRunnable("Set Writer") {
      @Override
      public void run2() throws CacheException {
        final Region<Object, Object> region = getRootRegion().getSubregion(name);
        setWriter(new TestCacheWriter<Object, Object>() {
          @Override
          public void beforeUpdate2(EntryEvent<Object, Object> event) throws CacheWriterException {

            Object argument = event.getCallbackArgument();
            if (exception.equals(argument)) {
              String s = "Test Exception";
              throw new CacheWriterException(s);
            }

            assertThat(argument).isEqualTo(arg);

            assertThat(event.getRegion()).isEqualTo(region);
            assertThat(event.getOperation().isUpdate()).isTrue();
            assertThat(event.getOperation().isDistributed()).isTrue();
            assertThat(event.getOperation().isExpiration()).isFalse();
            assertThat(event.isOriginRemote()).isTrue();
            assertThat(event.getKey()).isEqualTo(key);
            assertThat(event.getOldValue()).isEqualTo(oldValue);
            assertThat(event.getNewValue()).isEqualTo(newValue);
            assertThat(event.getOperation().isLoad()).isFalse();
            assertThat(event.getOperation().isLocalLoad()).isFalse();
            assertThat(event.getOperation().isNetLoad()).isFalse();
            assertThat(event.getOperation().isNetSearch()).isFalse();

          }
        });
        region.getAttributesMutator().setCacheWriter(writer());
      }
    });

    vm0.invoke(new CacheSerializableRunnable("Update with Exception") {
      @Override
      public void run2() throws CacheException {
        Region<Object, Object> region = getRootRegion().getSubregion(name);
        try {
          region.put(key, newValue, exception);
          fail("Should have thrown a CacheWriterException");

        } catch (CacheWriterException ex) {
          Region.Entry entry = region.getEntry(key);
          assertThat(entry.getValue()).isEqualTo(oldValue);
          assertThat(region.size()).isEqualTo(2);
          if (region.getAttributes().getOffHeap() && !(region instanceof PartitionedRegion)) {
            GemFireCacheImpl gfc = (GemFireCacheImpl) getCache();
            MemoryAllocatorImpl ma = (MemoryAllocatorImpl) gfc.getOffHeapStore();
            assertThat(ma.getStats().getObjects()).isEqualTo(2);
            LocalRegion reRegion;
            reRegion = (LocalRegion) region;
            StoredObject so = (StoredObject) reRegion.getRegionEntry(key).getValue();
            assertThat(so.getRefCount()).isEqualTo(1);
          }
        }
      }
    });
    vm1.invoke(new SerializableRunnable("Verify callback") {
      @Override
      public void run() {
        assertThat(writer().wasInvoked()).isTrue();
      }
    });

    vm0.invoke(new CacheSerializableRunnable("Update with Argument") {
      @Override
      public void run2() throws CacheException {
        Region<Object, Object> region = getRootRegion().getSubregion(name);
        region.put(key, newValue, arg);
        assertThat(region.size()).isEqualTo(2);
        if (region.getAttributes().getOffHeap() && !(region instanceof PartitionedRegion)) {
          GemFireCacheImpl gfc = (GemFireCacheImpl) getCache();
          MemoryAllocatorImpl ma = (MemoryAllocatorImpl) gfc.getOffHeapStore();
          assertThat(ma.getStats().getObjects()).isEqualTo(2);
        }
      }
    });
    vm1.invoke(new SerializableRunnable("Verify callback") {
      @Override
      public void run() {
        assertThat(writer().wasInvoked()).isTrue();
      }
    });

    //////// Destroy

    vm1.invoke(new CacheSerializableRunnable("Set Writer") {
      @Override
      public void run2() throws CacheException {
        final Region<Object, Object> region = getRootRegion().getSubregion(name);
        setWriter(new TestCacheWriter<Object, Object>() {
          @Override
          public void beforeDestroy2(EntryEvent<Object, Object> event) throws CacheWriterException {

            Object argument = event.getCallbackArgument();
            if (exception.equals(argument)) {
              String s = "Test Exception";
              throw new CacheWriterException(s);
            }

            assertThat(argument).isEqualTo(arg);

            assertThat(event.getRegion()).isEqualTo(region);
            assertThat(event.getOperation().isDestroy()).isTrue();
            assertThat(event.getOperation().isDistributed()).isTrue();
            assertThat(event.getOperation().isExpiration()).isFalse();
            assertThat(event.isOriginRemote()).isTrue();
            assertThat(event.getKey()).isEqualTo(key);
            assertThat(event.getOldValue()).isEqualTo(newValue);
            assertThat(event.getNewValue()).isNull();
            assertThat(event.getOperation().isLoad()).isFalse();
            assertThat(event.getOperation().isLocalLoad()).isFalse();
            assertThat(event.getOperation().isNetLoad()).isFalse();
            assertThat(event.getOperation().isNetSearch()).isFalse();
          }
        });
        region.getAttributesMutator().setCacheWriter(writer());
      }
    });

    vm0.invoke(new CacheSerializableRunnable("Destroy with Exception") {
      @Override
      public void run2() throws CacheException {
        Region<Object, Object> region = getRootRegion().getSubregion(name);
        try {
          region.destroy(key, exception);
          fail("Should have thrown a CacheWriterException");

        } catch (CacheWriterException ex) {
          assertThat(region.getEntry(key)).isNotNull();
          assertThat(region.size()).isEqualTo(2);
          if (region.getAttributes().getOffHeap() && !(region instanceof PartitionedRegion)) {
            GemFireCacheImpl gfc = (GemFireCacheImpl) getCache();
            MemoryAllocatorImpl ma = (MemoryAllocatorImpl) gfc.getOffHeapStore();
            assertThat(ma.getStats().getObjects()).isEqualTo(2);
          }
        }
      }
    });
    vm1.invoke(new SerializableRunnable("Verify callback") {
      @Override
      public void run() {
        assertThat(writer().wasInvoked()).isTrue();
      }
    });

    vm0.invoke(new CacheSerializableRunnable("Destroy with Argument") {
      @Override
      public void run2() throws CacheException {
        Region<Object, Object> region = getRootRegion().getSubregion(name);
        region.destroy(key, arg);
        assertThat(region.size()).isEqualTo(1);
        if (region.getAttributes().getOffHeap() && !(region instanceof PartitionedRegion)) {
          GemFireCacheImpl gfc = (GemFireCacheImpl) getCache();
          MemoryAllocatorImpl ma = (MemoryAllocatorImpl) gfc.getOffHeapStore();
          assertThat(ma.getStats().getObjects()).isEqualTo(1);
        }
      }
    });
    vm1.invoke(new SerializableRunnable("Verify callback") {
      @Override
      public void run() {
        assertThat(writer().wasInvoked()).isTrue();
      }
    });

    //////// Region Destroy

    vm1.invoke(new CacheSerializableRunnable("Set Writer") {
      @Override
      public void run2() throws CacheException {
        final Region<Object, Object> region = getRootRegion().getSubregion(name);
        setWriter(new TestCacheWriter<Object, Object>() {
          @Override
          public void beforeRegionDestroy2(RegionEvent<Object, Object> event)
              throws CacheWriterException {

            Object argument = event.getCallbackArgument();
            if (exception.equals(argument)) {
              String s = "Test Exception";
              throw new CacheWriterException(s);
            }

            assertThat(argument).isEqualTo(arg);

            assertThat(event.getRegion()).isEqualTo(region);
            assertThat(event.getOperation().isRegionDestroy()).isTrue();
            assertThat(event.getOperation().isDistributed()).isTrue();
            assertThat(event.getOperation().isExpiration()).isFalse();
            assertThat(event.isOriginRemote()).isTrue();
          }
        });
        region.getAttributesMutator().setCacheWriter(writer());
      }
    });

    vm0.invoke(new CacheSerializableRunnable("Destroy with Exception") {
      @Override
      public void run2() throws CacheException {
        Region<Object, Object> region = getRootRegion().getSubregion(name);
        try {
          region.destroyRegion(exception);
          fail("Should have thrown a CacheWriterException");

        } catch (CacheWriterException ex) {
          if (region.isDestroyed()) {
            fail("should not have an exception if region is destroyed", ex);
          }
          assertThat(region.size()).isEqualTo(1);
          if (region.getAttributes().getOffHeap() && !(region instanceof PartitionedRegion)) {
            GemFireCacheImpl gfc = (GemFireCacheImpl) getCache();
            MemoryAllocatorImpl ma = (MemoryAllocatorImpl) gfc.getOffHeapStore();
            assertThat(ma.getStats().getObjects()).isEqualTo(1);
          }
        }
      }
    });
    vm1.invoke(new SerializableRunnable("Verify callback") {
      @Override
      public void run() {
        assertThat(writer().wasInvoked()).isTrue();
      }
    });

    vm0.invoke(new CacheSerializableRunnable("Destroy with Argument") {
      @Override
      public void run2() throws CacheException {
        Region<Object, Object> region = getRootRegion().getSubregion(name);
        assertThat(region.size()).isEqualTo(1);
        if (region.getAttributes().getOffHeap() && !(region instanceof PartitionedRegion)) {
          GemFireCacheImpl gfc = (GemFireCacheImpl) getCache();
          MemoryAllocatorImpl ma = (MemoryAllocatorImpl) gfc.getOffHeapStore();
          assertThat(ma.getStats().getObjects()).isEqualTo(1);
        }
        region.destroyRegion(arg);
        if (region.getAttributes().getOffHeap() && !(region instanceof PartitionedRegion)) {
          GemFireCacheImpl gfc = (GemFireCacheImpl) getCache();
          final MemoryAllocatorImpl ma = (MemoryAllocatorImpl) gfc.getOffHeapStore();
          await("waiting for off-heap object count go to zero")
              .until(() -> ma.getStats().getObjects(), equalTo(0));

        }
      }
    });
    vm1.invoke(new SerializableRunnable("Verify callback") {
      @Override
      public void run() {
        assertThat(writer().wasInvoked()).isTrue();
      }
    });
  }

  /**
   * Tests that, when given a choice, a local <code>CacheWriter</code> is invoked instead of a
   * remote one.
   */
  @Test
  public void testLocalAndRemoteCacheWriters() {
    assertThat(getRegionAttributes().getScope().isDistributed()).isTrue();

    final String name = this.getUniqueName();
    final Object key = "KEY";
    final Object oldValue = "OLD_VALUE";
    final Object newValue = "NEW_VALUE";

    VM vm0 = VM.getVM(0);
    VM vm1 = VM.getVM(1);

    vm0.invoke(new CacheSerializableRunnable("Create \"Local\" Region") {
      @Override
      public void run2() throws CacheException {
        Region<Object, Object> region = createRegion(name);
        setWriter(new TestCacheWriter<Object, Object>() {
          @Override
          public void beforeUpdate2(EntryEvent<Object, Object> event) throws CacheWriterException {}

          @Override
          public void beforeCreate2(EntryEvent<Object, Object> event) throws CacheWriterException {}

          @Override
          public void beforeDestroy2(EntryEvent<Object, Object> event)
              throws CacheWriterException {}

          @Override
          public void beforeRegionDestroy2(RegionEvent<Object, Object> event)
              throws CacheWriterException {}
        });
        region.getAttributesMutator().setCacheWriter(writer());
      }
    });

    SerializableRunnable create = new CacheSerializableRunnable("Create \"Local\" Region") {
      @Override
      public void run2() throws CacheException {
        Region<Object, Object> region = createRegion(name);
        setWriter(new TestCacheWriter<Object, Object>() {});
        region.getAttributesMutator().setCacheWriter(writer());
      }
    };

    vm1.invoke(create);

    SerializableRunnable verify = new SerializableRunnable("Verify no callback") {
      @Override
      public void run() {
        assertThat(writer().wasInvoked()).isFalse();
      }
    };

    vm0.invoke(new CacheSerializableRunnable("Create entry") {
      @Override
      public void run2() throws CacheException {
        Region<Object, Object> region = getRootRegion().getSubregion(name);
        region.put(key, oldValue);
        assertThat(writer().wasInvoked()).isTrue();
      }
    });
    vm1.invoke(verify);

    vm0.invoke(new CacheSerializableRunnable("Update entry") {
      @Override
      public void run2() throws CacheException {
        Region<Object, Object> region = getRootRegion().getSubregion(name);
        region.put(key, newValue);
        assertThat(writer().wasInvoked()).isTrue();
      }
    });
    vm1.invoke(verify);

    vm0.invoke(new CacheSerializableRunnable("Destroy entry") {
      @Override
      public void run2() throws CacheException {
        Region<Object, Object> region = getRootRegion().getSubregion(name);
        region.destroy(key);
        assertThat(writer().wasInvoked()).isTrue();
      }
    });
    vm1.invoke(verify);

    vm0.invoke(new CacheSerializableRunnable("Destroy region") {
      @Override
      public void run2() throws CacheException {
        Region<Object, Object> region = getRootRegion().getSubregion(name);
        region.destroyRegion();
        assertThat(writer().wasInvoked()).isTrue();
      }
    });
    vm1.invoke(verify);
  }

  /**
   * Tests that when a <code>CacheLoader</code> modifies the callback argument in place, the change
   * is visible to the <code>CacheWriter</code> even if it is in another VM.
   */
  @Test
  public void testCacheLoaderModifyingArgument() {
    assertThat(getRegionAttributes().getScope().isDistributed()).isTrue();

    final String name = this.getUniqueName();
    final Object key = "KEY";
    final Object value = "VALUE";
    final Object one = "ONE";
    final Object two = "TWO";

    SerializableRunnable create = new CacheSerializableRunnable("Create Region") {
      @Override
      public void run2() throws CacheException {
        createRegion(name);
      }
    };

    final VM vm0 = VM.getVM(0);
    final VM vm1 = VM.getVM(1);

    vm0.invoke(create);
    vm1.invoke(create);

    CacheSerializableRunnable setLoader = new CacheSerializableRunnable("Set CacheLoader") {
      @Override
      public void run2() throws CacheException {
        final Region<Object, Object> region = getRootRegion().getSubregion(name);
        setLoader(new TestCacheLoader<Object, Object>() {
          @Override
          public Object load2(LoaderHelper<Object, Object> helper) throws CacheLoaderException {

            Object[] array = (Object[]) helper.getArgument();
            assertThat(array[0]).isEqualTo(one);
            array[0] = two;
            return value;
          }
        });
        region.getAttributesMutator().setCacheLoader(loader());
        flushIfNecessary(region);
      }
    };

    vm0.invoke(setLoader);

    // if this is a partitioned region, we need the loader in both vms
    vm1.invoke(new CacheSerializableRunnable("Conditionally create second loader") {
      @Override
      public void run2() throws CacheException {
        final Region<Object, Object> region = getRootRegion().getSubregion(name);
        if (region.getAttributes().getPartitionAttributes() != null) {
          setLoader(new TestCacheLoader<Object, Object>() {
            @Override
            public Object load2(LoaderHelper<Object, Object> helper) throws CacheLoaderException {

              Object[] array = (Object[]) helper.getArgument();
              assertThat(array[0]).isEqualTo(one);
              array[0] = two;
              return value;
            }
          });
          region.getAttributesMutator().setCacheLoader(loader());
        }
      }
    });

    vm1.invoke(new CacheSerializableRunnable("Set CacheWriter") {
      @Override
      public void run2() throws CacheException {
        final Region<Object, Object> region = getRootRegion().getSubregion(name);
        setWriter(new TestCacheWriter<Object, Object>() {
          @Override
          public void beforeCreate2(EntryEvent<Object, Object> event) throws CacheWriterException {

            Object[] array = (Object[]) event.getCallbackArgument();
            assertThat(array[0]).isEqualTo(two);
          }
        });
        region.getAttributesMutator().setCacheWriter(writer());
        flushIfNecessary(region);
      }
    });

    vm0.invoke(new CacheSerializableRunnable("Create entry") {
      @Override
      public void run2() throws CacheException {
        Region<Object, Object> region = getRootRegion().getSubregion(name);
        Object[] array = {one};
        Object result = region.get(key, array);
        assertThat(loader().wasInvoked()).isTrue();
        assertThat(result).isEqualTo(value);
      }
    });

    vm1.invoke(new CacheSerializableRunnable("Validate callback") {
      @Override
      public void run2() throws CacheException {
        assertThat(writer().wasInvoked()).isTrue();
      }
    });
  }

  /**
   * Tests that invoking <code>netSearch</code> in a remote loader returns <code>null</code> instead
   * of causing infinite recursion.
   */
  @Test
  public void testRemoteLoaderNetSearch() {
    assumeThat(supportsNetLoad()).isTrue();

    assertThat(getRegionAttributes().getScope().isDistributed()).isTrue();

    final String name = this.getUniqueName();
    final Object key = "KEY";
    final Object value = "VALUE";

    final VM vm0 = VM.getVM(0);
    final VM vm1 = VM.getVM(1);

    SerializableRunnable create = new CacheSerializableRunnable("Get value") {
      @Override
      public void run2() throws CacheException {
        Region<Object, Object> region = createRegion(name);
        assertThat(region.get(key)).isEqualTo(value);
      }
    };

    vm0.invoke(new CacheSerializableRunnable("Create Region") {
      @Override
      public void run2() throws CacheException {
        Region<Object, Object> region = createRegion(name);
        region.getAttributesMutator().setCacheLoader(new TestCacheLoader<Object, Object>() {
          @Override
          public Object load2(LoaderHelper<Object, Object> helper) throws CacheLoaderException {

            try {
              assertThat(helper.netSearch(true)).isNull();

            } catch (TimeoutException ex) {
              fail("Why did I time out?", ex);
            }
            return value;
          }
        });
      }
    });

    vm1.invoke(create);
  }

  /**
   * Tests that a local loader is preferred to a remote one
   */
  @Test
  public void testLocalCacheLoader() {
    final String name = this.getUniqueName();
    final Object key = "KEY";
    final Object value = "VALUE";

    final VM vm0 = VM.getVM(0);
    final VM vm1 = VM.getVM(1);

    SerializableRunnable create = new CacheSerializableRunnable("Create \"remote\" region") {
      @Override
      public void run2() throws CacheException {
        Region<Object, Object> region = createRegion(name);
        setLoader(new TestCacheLoader<Object, Object>() {
          @Override
          public Object load2(LoaderHelper<Object, Object> helper) throws CacheLoaderException {
            if (helper.getRegion().getAttributes().getPartitionAttributes() == null) {
              fail("Should not be invoked");
              return null;
            } else {
              return value;
            }
          }
        });
        region.getAttributesMutator().setCacheLoader(loader());
      }
    };

    vm0.invoke(new CacheSerializableRunnable("Create \"local\" region") {
      @Override
      public void run2() throws CacheException {
        Region<Object, Object> region = createRegion(name);
        region.getAttributesMutator().setCacheLoader(new TestCacheLoader<Object, Object>() {
          @Override
          public Object load2(LoaderHelper<Object, Object> helper) throws CacheLoaderException {
            return value;
          }
        });
      }
    });

    vm1.invoke(create);

    vm0.invoke(new CacheSerializableRunnable("Get") {
      @Override
      public void run2() throws CacheException {
        Region<Object, Object> region = getRootRegion().getSubregion(name);
        assertThat(region.get(key)).isEqualTo(value);
      }
    });
    vm1.invoke(new SerializableRunnable("Verify loader not invoked") {
      @Override
      public void run() {
        assertThat(loader().wasInvoked()).isFalse();
      }
    });
  }

  /**
   * Tests that an entry update is propagated to other caches that have that same entry defined.
   */
  @Test
  public void testDistributedPut() {
    final String rgnName = getUniqueName();

    SerializableRunnable create = new SerializableRunnable("testDistributedPut: Create Region") {
      @Override
      public void run() {
        try {
          createRegion(rgnName);
          getSystem().getLogWriter().info("testDistributedPut: Created Region");
        } catch (CacheException e) {
          fail("While creating region", e);
        }
      }
    };

    SerializableRunnable newKey = new SerializableRunnable("testDistributedPut: Create Key") {
      @Override
      public void run() {
        try {
          if (!getRegionAttributes().getDataPolicy().withReplication()
              && getRegionAttributes().getPartitionAttributes() == null) {
            Region<?, ?> root = getRootRegion("root");
            Region<Object, Object> rgn = root.getSubregion(rgnName);
            rgn.create("key", null);
            getSystem().getLogWriter().info("testDistributedPut: Created Key");
          }
        } catch (CacheException e) {
          fail("While creating region", e);
        }
      }
    };

    final VM vm0 = VM.getVM(0);

    vm0.invoke(create);
    vm0.invoke(newKey);
    int vmCount = VM.getVMCount();

    for (int i = 1; i < vmCount; i++) {
      VM vm = VM.getVM(i);
      vm.invoke(create);
      if (!getRegionAttributes().getDataPolicy().withPreloaded()) {
        vm.invoke(newKey);
      }
    }

    try {
      Region<String, String> rgn = createRegion(rgnName);

      rgn.put("key", "value");
      getSystem().getLogWriter().info("testDistributedPut: Put Value");

      invokeInEveryVM(repeatingIfNecessary(
          new CacheSerializableRunnable("testDistributedPut: Verify Received Value") {
            @Override
            public void run2() {
              Region<String, String> rgn1 = getRootRegion().getSubregion(rgnName);
              String description = "Could not find entry for 'key'";
              Object actual = rgn1.getEntry("key");
              assertThat(actual).describedAs(description).isNotNull();
              assertThat(rgn1.getEntry("key").getValue()).isEqualTo("value");
            }
          }));

    } catch (Exception e) {
      getCache().close();
      getSystem().getLogWriter().fine("testDistributedPut: Caused exception in createRegion");
      throw e;
    }

  }


  /**
   * Indicate whether replication/GII supported
   *
   * @return true if replication is supported
   */
  protected boolean supportsReplication() {
    return true;
  }

  /**
   * Tests that keys and values are pushed with {@link DataPolicy#REPLICATE}.
   */
  @Test
  public void testReplicate() {
    assumeThat(supportsReplication()).isTrue();

    final String name = this.getUniqueName();
    final Object key1 = "KEY1";
    final Object value1 = "VALUE1";
    final Object key2 = "KEY2";

    Object[] v = new Object[3000];
    Arrays.fill(v, 0xCAFE);

    final Object value2 = Arrays.asList(v);
    final Object key3 = "KEY3";
    final Object value3 = "VALUE3";

    VM vm0 = VM.getVM(0);
    VM vm2 = VM.getVM(2); // use VM on separate shared memory in case shared regions

    SerializableRunnable create = new CacheSerializableRunnable("Create Mirrored Region") {
      @Override
      public void run2() throws CacheException {
        RegionAttributes<?, ?> ra = getRegionAttributes();
        AttributesFactory<?, ?> factory = new AttributesFactory<>(ra);
        if (ra.getEvictionAttributes() == null
            || !ra.getEvictionAttributes().getAction().isOverflowToDisk()) {
          factory.setDiskStoreName(null);
        }
        factory.setDataPolicy(DataPolicy.REPLICATE);
        createRegion(name, factory.create());
      }
    };

    vm0.invoke(create);
    vm2.invoke(create);

    vm0.invoke(new CacheSerializableRunnable("Put data") {
      @Override
      public void run2() throws CacheException {
        Region<Object, Object> region = getRootRegion().getSubregion(name);
        region.put(key1, value1);
        region.put(key2, value2);
        region.put(key3, value3);
        flushIfNecessary(region);
      }
    });

    vm2.invoke(repeatingIfNecessary(new CacheSerializableRunnable("Wait for update") {
      @Override
      public void run2() throws CacheException {
        Region<Object, Object> region = getRootRegion().getSubregion(name);
        assertThat(region.getEntry(key1)).isNotNull();
        assertThat(region.getEntry(key2)).isNotNull();
        assertThat(region.getEntry(key3)).isNotNull();
      }
    }));

    // Destroy the local entries so we know that they are not found by
    // a netSearch
    vm0.invoke(new CacheSerializableRunnable("Remove local entries") {
      @Override
      public void run2() throws CacheException {
        Region<Object, Object> region = getRootRegion().getSubregion(name);
        region.localDestroyRegion();
        flushIfNecessary(region);
      }
    });

    vm2.invoke(repeatingIfNecessary(new CacheSerializableRunnable("Verify keys") {
      @Override
      public void run2() throws CacheException {
        Region<Object, Object> region = getRootRegion().getSubregion(name);

        // small
        Region.Entry<Object, Object> entry1 = region.getEntry(key1);
        assertThat(entry1).isNotNull();
        assertThat(entry1.getValue()).isEqualTo(value1);

        // large
        Region.Entry<Object, Object> entry2 = region.getEntry(key2);
        assertThat(entry2).isNotNull();
        assertThat(entry2.getValue()).isEqualTo(value2);

        // small
        Region.Entry<Object, Object> entry3 = region.getEntry(key3);
        assertThat(entry3).isNotNull();
        assertThat(entry3.getValue()).isEqualTo(value3);
      }
    }));
  }

  /**
   * Tests that a newly-created mirrored region contains all of the entries of another region.
   */
  @Test
  public void testGetInitialImage() {
    assumeThat(supportsReplication()).isTrue();

    final String name = this.getUniqueName();
    final Object key1 = "KEY1";
    final Object value1 = "VALUE1";
    final Object key2 = "KEY2";
    final Object value2 = "VALUE2";
    final Object key3 = "KEY3";
    final Object value3 = "VALUE3";

    VM vm0 = VM.getVM(0);
    VM vm2 = VM.getVM(2); // use VM on different shared memory area

    SerializableRunnable create = new CacheSerializableRunnable("Create Mirrored Region") {
      @Override
      public void run2() throws CacheException {
        RegionAttributes<?, ?> ra = getRegionAttributes();
        AttributesFactory<?, ?> factory = new AttributesFactory<>(ra);
        if (ra.getEvictionAttributes() == null
            || !ra.getEvictionAttributes().getAction().isOverflowToDisk()) {
          factory.setDiskStoreName(null);
        }
        factory.setDataPolicy(DataPolicy.REPLICATE);
        createRegion(name, factory.create());
      }
    };

    vm0.invoke(create);

    vm0.invoke(new CacheSerializableRunnable("Put data") {
      @Override
      public void run2() throws CacheException {
        Region<Object, Object> region = getRootRegion().getSubregion(name);
        region.put(key1, value1);
        region.put(key2, value2);
        region.put(key3, value3);
      }
    });

    vm2.invoke(create);

    // Destroy the local entries so we know that they are not found by
    // a netSearch
    vm0.invoke(new CacheSerializableRunnable("Remove local entries") {
      @Override
      public void run2() throws CacheException {
        Region<Object, Object> region = getRootRegion().getSubregion(name);
        region.localDestroyRegion();
      }
    });

    vm2.invoke(new CacheSerializableRunnable("Verify keys/values") {
      @Override
      public void run2() throws CacheException {
        Region<Object, Object> region = getRootRegion().getSubregion(name);

        Region.Entry entry1 = region.getEntry(key1);
        assertThat(entry1).isNotNull();
        assertThat(entry1.getValue()).isEqualTo(value1);

        Region.Entry entry2 = region.getEntry(key2);
        assertThat(entry2).isNotNull();
        assertThat(entry2.getValue()).isEqualTo(value2);

        Region.Entry entry3 = region.getEntry(key3);
        assertThat(entry3).isNotNull();
        assertThat(entry3.getValue()).isEqualTo(value3);
      }
    });
  }

  private static final int CHUNK_SIZE = 500 * 1024; // == InitialImageOperation.CHUNK_SIZE_IN_BYTES
  private static final int NUM_ENTRIES = 100;
  private static final int VALUE_SIZE = CHUNK_SIZE * 10 / NUM_ENTRIES;

  /**
   * Tests that a newly-created mirrored region contains all of the entries of another region, with
   * a large quantity of data.
   */
  @Test
  public void testLargeGetInitialImage() {
    assumeThat(supportsReplication()).isTrue();

    final String name = this.getUniqueName();
    final Integer[] keys = new Integer[NUM_ENTRIES];
    final byte[][] values = new byte[NUM_ENTRIES][];

    for (int i = 0; i < NUM_ENTRIES; i++) {
      keys[i] = i;
      values[i] = new byte[VALUE_SIZE];
      Arrays.fill(values[i], (byte) 0x42);
    }

    VM vm0 = VM.getVM(0);
    VM vm2 = VM.getVM(2); // use VM on different shared memory area

    SerializableRunnable create = new CacheSerializableRunnable("Create Mirrored Region") {
      @Override
      public void run2() throws CacheException {
        RegionAttributes<?, ?> ra = getRegionAttributes();
        AttributesFactory<?, ?> factory = new AttributesFactory<>(ra);
        if (ra.getEvictionAttributes() == null
            || !ra.getEvictionAttributes().getAction().isOverflowToDisk()) {
          factory.setDiskStoreName(null);
        }
        factory.setDataPolicy(DataPolicy.REPLICATE);
        createRegion(name, factory.create());
      }
    };

    vm0.invoke(create);

    vm0.invoke(new CacheSerializableRunnable("Put data") {
      @Override
      public void run2() throws CacheException {
        Region<Integer, byte[]> region = getRootRegion().getSubregion(name);
        for (int i = 0; i < NUM_ENTRIES; i++) {
          region.put(keys[i], values[i]);
        }
      }
    });

    vm2.invoke(create);

    // Destroy the local entries so we know that they are not found by
    // a netSearch
    vm0.invoke(new CacheSerializableRunnable("Remove local entries") {
      @Override
      public void run2() throws CacheException {
        Region<Object, Object> region = getRootRegion().getSubregion(name);
        region.localDestroyRegion();
      }
    });

    vm2.invoke(new CacheSerializableRunnable("Verify keys/values") {
      @Override
      public void run2() throws CacheException {
        Region<Object, Object> region = getRootRegion().getSubregion(name);
        assertThat(region.entrySet(false).size()).isEqualTo(NUM_ENTRIES);
        for (int i = 0; i < NUM_ENTRIES; i++) {
          Region.Entry entry = region.getEntry(keys[i]);
          assertThat(entry).isNotNull();
          if (!(entry.getValue() instanceof byte[])) {
            fail("getValue returned a " + entry.getValue().getClass()
                + " instead of the expected byte[]");
          }
          assertThat(Arrays.equals(values[i], (byte[]) entry.getValue())).isTrue();
        }
      }
    });
  }

  /**
   * Tests that a mirrored region gets data pushed to it from a non-mirrored region and the
   * afterCreate event is invoked on a listener.
   */
  @Test
  public void testMirroredDataFromNonMirrored() {
    assumeThat(supportsReplication()).isTrue();

    final String name = this.getUniqueName();
    final Object key1 = "KEY1";
    final Object value1 = "VALUE1";
    final Object key2 = "KEY2";
    final Object value2 = "VALUE2";
    final Object key3 = "KEY3";
    final Object value3 = "VALUE3";

    VM vm0 = VM.getVM(0);
    VM vm2 = VM.getVM(2); // use a VM on a different gemfire system

    SerializableRunnable create = new CacheSerializableRunnable("Populate non-mirrored region") {
      @Override
      public void run2() throws CacheException {
        RegionAttributes<Object, Object> ra = getRegionAttributes();
        AttributesFactory<Object, Object> fac = new AttributesFactory<>(ra);
        if (ra.getEvictionAttributes() == null
            || !ra.getEvictionAttributes().getAction().isOverflowToDisk()) {
          fac.setDiskStoreName(null);
        }
        fac.setDataPolicy(DataPolicy.NORMAL);
        // fac.setPersistBackup(false);
        Region<Object, Object> region = createRegion(name, fac.create());
        region.put(key1, value1);
        region.put(key2, value2);
        region.put(key3, value3);
        flushIfNecessary(region);
      }
    };

    class MirroredDataFromNonMirroredListener extends TestCacheListener<Object, Object> {
      // use modifiable ArrayLists
      final List<Object> expectedKeys = new ArrayList<>(Arrays.asList(key1, key2, key3));
      final List<Object> expectedValues = new ArrayList<>(Arrays.asList(value1, value2, value3));

      @Override
      public synchronized void afterCreate2(EntryEvent<Object, Object> event) {
        // getLogWriter().info("Invoking afterCreate2 with key=" + event.getKey());
        int index = expectedKeys.indexOf(event.getKey());
        assertThat(index >= 0).isTrue();
        assertThat(event.getNewValue()).isEqualTo(expectedValues.remove(index));
        expectedKeys.remove(index);
        logger.info("afterCreate called in "
            + "MirroredDataFromNonMirroredListener for key:" + event.getKey());
      }
    }

    vm0.invoke(new CacheSerializableRunnable("Create Mirrored Region") {
      @Override
      public void run2() throws CacheException {
        RegionAttributes<Object, Object> ra = getRegionAttributes();
        AttributesFactory<Object, Object> factory = new AttributesFactory<>(ra);
        if (ra.getEvictionAttributes() == null
            || !ra.getEvictionAttributes().getAction().isOverflowToDisk()) {
          factory.setDiskStoreName(null);
        }
        factory.setDataPolicy(DataPolicy.REPLICATE);
        factory.addCacheListener(new MirroredDataFromNonMirroredListener());
        createRegion(name, factory.create());
      }
    });

    vm2.invoke(create);

    // Destroy the local entries so we know that they are not found by
    // a netSearch
    vm2.invoke(new CacheSerializableRunnable("Remove local entries") {
      @Override
      public void run2() throws CacheException {
        Region<Object, Object> region = getRootRegion().getSubregion(name);
        region.localDestroy(key1);
        region.localDestroy(key2);
        region.localDestroy(key3);
        flushIfNecessary(region);
      }
    });

    vm0.invoke(new CacheSerializableRunnable("Verify keys/values and listener") {
      @Override
      public void run2() throws CacheException {
        Region<Object, Object> region = getRootRegion().getSubregion(name);

        Region.Entry entry1 = region.getEntry(key1);
        assertThat(entry1).isNotNull();
        assertThat(entry1.getValue()).isEqualTo(value1);

        Region.Entry entry2 = region.getEntry(key2);
        assertThat(entry2).isNotNull();
        assertThat(entry2.getValue()).isEqualTo(value2);

        Region.Entry entry3 = region.getEntry(key3);
        assertThat(entry3).isNotNull();
        assertThat(entry3.getValue()).isEqualTo(value3);

        MirroredDataFromNonMirroredListener lsnr =
            (MirroredDataFromNonMirroredListener) region.getAttributes().getCacheListeners()[0];

        assertThat(lsnr.wasInvoked()).isTrue();
        assertThat(lsnr.expectedKeys.isEmpty()).describedAs(
            "expectedKeys should be empty, but was: " + lsnr.expectedKeys).isTrue();
      }
    });
  }


  /**
   * Tests that a mirrored region does not push data to a non-mirrored region.
   */
  @Test
  public void testNoMirroredDataToNonMirrored() {
    assumeThat(supportsReplication()).isTrue();

    final String name = this.getUniqueName();
    final Object key1 = "KEY1";
    final Object value1 = "VALUE1";
    final Object key2 = "KEY2";
    final Object value2 = "VALUE2";
    final Object key3 = "KEY3";
    final Object value3 = "VALUE3";

    VM vm0 = VM.getVM(0);
    VM vm2 = VM.getVM(2); // use VM on different gemfire system

    vm0.invoke(new CacheSerializableRunnable("Create Non-mirrored Region") {
      @Override
      public void run2() throws CacheException {
        createRegion(name, getRegionAttributes());
      }
    });

    SerializableRunnable create = new CacheSerializableRunnable("Populate mirrored region") {
      @Override
      public void run2() throws CacheException {
        RegionAttributes<Object, Object> ra = getRegionAttributes();
        AttributesFactory<Object, Object> factory = new AttributesFactory<>(ra);
        if (ra.getEvictionAttributes() == null
            || !ra.getEvictionAttributes().getAction().isOverflowToDisk()) {
          factory.setDiskStoreName(null);
        }
        factory.setDataPolicy(DataPolicy.REPLICATE);
        Region<Object, Object> region = createRegion(name, factory.create());
        region.put(key1, value1);
        region.put(key2, value2);
        region.put(key3, value3);
        flushIfNecessary(region);
      }
    };

    vm2.invoke(create);

    // Make sure that data wasn't pushed
    vm0.invoke(new CacheSerializableRunnable("Verify keys/values") {
      @Override
      public void run2() throws CacheException {
        final Region<Object, Object> region = getRootRegion().getSubregion(name);
        Region.Entry entry1 = region.getEntry(key1);
        if (!getRegionAttributes().getDataPolicy().withReplication()) {
          if (entry1 != null) {
            logger.info("found entry " + entry1);
          }
          assertThat(entry1).isNull();
        } else {
          assertThat(entry1).isNotNull();
        }

        Region.Entry entry2 = region.getEntry(key2);
        if (!getRegionAttributes().getDataPolicy().withReplication()) {
          assertThat(entry2).isNull();
        } else {
          assertThat(entry2).isNotNull();
        }

        Region.Entry entry3 = region.getEntry(key3);
        if (!getRegionAttributes().getDataPolicy().withReplication()) {
          assertThat(entry3).isNull();
        } else {
          assertThat(entry3).isNotNull();
        }
      }
    });
  }

  /**
   * Tests that a local load occurs, even with mirroring
   */
  @Test
  public void testMirroredLocalLoad() {
    assumeThat(supportsReplication()).isTrue();

    final String name = this.getUniqueName();
    final Object key = "KEY";
    final Object value = "VALUE";

    VM vm0 = VM.getVM(0);
    VM vm2 = VM.getVM(2); // use VMs on different gemfire systems

    vm0.invoke(new CacheSerializableRunnable("Create region with loader") {
      @Override
      public void run2() throws CacheException {
        RegionAttributes<Object, Object> ra = getRegionAttributes();
        AttributesFactory<Object, Object> factory = new AttributesFactory<>(ra);
        if (ra.getEvictionAttributes() == null
            || !ra.getEvictionAttributes().getAction().isOverflowToDisk()) {
          factory.setDiskStoreName(null);
        }
        factory.setDataPolicy(DataPolicy.REPLICATE);
        factory.setCacheLoader(new TestCacheLoader<Object, Object>() {
          @Override
          public Object load2(LoaderHelper<Object, Object> helper) throws CacheLoaderException {
            return value;
          }
        });
        createRegion(name, factory.create());
      }
    });

    SerializableRunnable create = new CacheSerializableRunnable("Create region with bad loader") {
      @Override
      public void run2() throws CacheException {
        RegionAttributes<Object, Object> ra = getRegionAttributes();
        AttributesFactory<Object, Object> factory = new AttributesFactory<>(ra);
        if (ra.getEvictionAttributes() == null
            || !ra.getEvictionAttributes().getAction().isOverflowToDisk()) {
          factory.setDiskStoreName(null);
        }
        factory.setDataPolicy(DataPolicy.REPLICATE);
        setLoader(new TestCacheLoader<Object, Object>() {
          @Override
          public Object load2(LoaderHelper<Object, Object> helper) throws CacheLoaderException {

            fail("Should not be invoked");
            return null;
          }
        });
        factory.setCacheLoader(loader());
        createRegion(name, factory.create());
      }
    };

    vm2.invoke(create);

    vm0.invoke(new CacheSerializableRunnable("Get") {
      @Override
      public void run2() throws CacheException {
        Region<Object, Object> region = getRootRegion().getSubregion(name);
        assertThat(region.get(key)).isEqualTo(value);
      }
    });

    vm2.invoke(new CacheSerializableRunnable("Verify no load") {
      @Override
      public void run2() throws CacheException {
        assertThat(loader().wasInvoked()).isFalse();
      }
    });
  }

  /**
   * Tests sure that a <code>netLoad</code> occurs, even with mirroring
   */
  @Test
  public void testMirroredNetLoad() {
    assumeThat(supportsReplication()).isTrue();

    final String name = this.getUniqueName();
    final Object key = "KEY";
    final Object value = "VALUE";

    VM vm0 = VM.getVM(0);
    VM vm2 = VM.getVM(2); // use VMs on different gemfire systems

    SerializableRunnable create = new CacheSerializableRunnable("Create region with loader") {
      @Override
      public void run2() throws CacheException {
        RegionAttributes<Object, Object> ra = getRegionAttributes();
        AttributesFactory<Object, Object> factory = new AttributesFactory<>(ra);
        if (ra.getEvictionAttributes() == null
            || !ra.getEvictionAttributes().getAction().isOverflowToDisk()) {
          factory.setDiskStoreName(null);
        }
        factory.setDataPolicy(DataPolicy.REPLICATE);
        factory.setCacheLoader(new TestCacheLoader<Object, Object>() {
          @Override
          public Object load2(LoaderHelper<Object, Object> helper) throws CacheLoaderException {
            return value;
          }
        });
        createRegion(name, factory.create());
      }
    };

    vm0.invoke(new CacheSerializableRunnable("Create region with bad loader") {
      @Override
      public void run2() throws CacheException {
        RegionAttributes<Object, Object> ra = getRegionAttributes();
        AttributesFactory<Object, Object> factory = new AttributesFactory<>(ra);
        if (ra.getEvictionAttributes() == null
            || !ra.getEvictionAttributes().getAction().isOverflowToDisk()) {
          factory.setDiskStoreName(null);
        }
        factory.setDataPolicy(DataPolicy.REPLICATE);
        createRegion(name, factory.create());
      }
    });

    vm2.invoke(create);

    vm0.invoke(new CacheSerializableRunnable("Get") {
      @Override
      public void run2() throws CacheException {
        Region<Object, Object> region = getRootRegion().getSubregion(name);
        assertThat(region.get(key)).isEqualTo(value);
      }
    });
  }

  /**
   * Tests that a region is not kept alive
   */
  @Test
  public void testNoRegionKeepAlive() {
    final String name = this.getUniqueName();
    final Object key = "KEEP_ALIVE_KEY";
    final Object value = "VALUE";

    VM vm0 = VM.getVM(0);

    vm0.invoke(new CacheSerializableRunnable("Create region") {
      @Override
      public void run2() throws CacheException {
        createRegion(name);
      }
    });

    vm0.invoke(new CacheSerializableRunnable("Populate region") {
      @Override
      public void run2() throws CacheException {
        Region<Object, Object> region = getRootRegion().getSubregion(name);
        region.put(key, value);
        assertThat(region.get(key)).isEqualTo(value);
      }
    });
    vm0.invoke(new CacheSerializableRunnable("Close cache") {
      @Override
      public void run2() throws CacheException {
        closeCache();
      }
    });

    vm0.invoke(new CacheSerializableRunnable("Re-create cache") {
      @Override
      public void run2() throws CacheException {
        Region<Object, Object> region = createRegion(name);
        // if this is a backup region, then it will find the data
        // otherwise it should not
        if (region.getAttributes().getDataPolicy().withPersistence()) {
          assertThat(region.get(key)).isEqualTo(value);
        } else {
          assertThat(region.get(key)).isNull();
        }
      }
    });
  }

  @Test
  public void testNetSearchObservesTtl() {
    assumeThat(getRegionAttributes().getPartitionAttributes())
        .withFailMessage("the region has partition attributes").isNull();

    final String name = this.getUniqueName();
    final int shortTimeout = 10; // ms
    final int longTimeout = 1000000; // ms
    final Object key = "KEY";
    final Object value = "VALUE";

    VM vm0 = VM.getVM(0);
    VM vm1 = VM.getVM(2); // Other VM is from a different gemfire system

    SerializableRunnable create = new CacheSerializableRunnable("Create with TTL") {
      @Override
      public void run2() throws CacheException {
        AttributesFactory<Object, Object> factory = new AttributesFactory<>(getRegionAttributes());
        factory.setStatisticsEnabled(true);
        ExpirationAttributes expire =
            new ExpirationAttributes(longTimeout, ExpirationAction.DESTROY);
        factory.setEntryTimeToLive(expire);
        System.setProperty(LocalRegion.EXPIRY_MS_PROPERTY, "true");
        try {
          Region<Object, Object> region = createRegion(name, factory.create());
          region.create(key, value);
        } finally {
          System.getProperties().remove(LocalRegion.EXPIRY_MS_PROPERTY);
        }
      }
    };

    vm1.invoke(create);

    // vm0 - Create region, short timeout
    vm0.invoke(new CacheSerializableRunnable("Create with TTL") {
      @Override
      public void run2() throws CacheException {
        RegionAttributes<?, ?> ra = getRegionAttributes();
        AttributesFactory<?, ?> factory = new AttributesFactory<>(ra);
        final boolean partitioned =
            ra.getPartitionAttributes() != null || ra.getDataPolicy().withPartitioning();
        // MUST be nonmirrored, so turn off persistBackup if this is a disk region test
        if (!partitioned) {
          if (ra.getEvictionAttributes() == null
              || !ra.getEvictionAttributes().getAction().isOverflowToDisk()) {
            factory.setDiskStoreName(null);
          }
          factory.setDataPolicy(DataPolicy.NORMAL);
        }
        factory.setStatisticsEnabled(true);
        ExpirationAttributes expire =
            new ExpirationAttributes(shortTimeout, ExpirationAction.DESTROY);
        factory.setEntryTimeToLive(expire);
        System.setProperty(LocalRegion.EXPIRY_MS_PROPERTY, "true");
        try {
          createRegion(name, factory.create());
        } finally {
          System.getProperties().remove(LocalRegion.EXPIRY_MS_PROPERTY);
        }
      }
    });

    Wait.pause(shortTimeout * 10);

    // Even though netSearch finds vm1's entry is not expired, it is considered
    // expired with respect to vm0's attributes
    vm0.invoke(new CacheSerializableRunnable("get(key), expect null") {
      @Override
      public void run2() throws CacheException {
        Region<Object, Object> region = getRootRegion().getSubregion(name);
        Object got = region.get(key);
        assertThat(got).isNull();
      }
    });

    // We see the object is actually still there
    vm1.invoke(new CacheSerializableRunnable("get(key), expect value") {
      @Override
      public void run2() throws CacheException {
        Region<Object, Object> region = getRootRegion().getSubregion(name);
        Object got = region.get(key);
        assertThat(got).isEqualTo(value);
      }
    });
  }

  @Test
  public void testNetSearchObservesIdleTime() {
    assumeThat(getRegionAttributes().getPartitionAttributes())
        .withFailMessage("the region has partition attributes").isNull();

    final String name = this.getUniqueName();
    final int shortTimeout = 10; // ms
    final int longTimeout = 10000; // ms
    final Object key = "KEY";
    final Object value = "VALUE";

    // if using shared memory, make sure we use two VMs on different
    // gemfire systems

    final VM vm0 = VM.getVM(0);
    final VM vm1 = VM.getVM(2);

    SerializableRunnable create = new CacheSerializableRunnable("Create with IdleTimeout") {
      @Override
      public void run2() throws CacheException {
        AttributesFactory<Object, Object> factory = new AttributesFactory<>(getRegionAttributes());
        factory.setStatisticsEnabled(true);
        ExpirationAttributes expire =
            new ExpirationAttributes(longTimeout, ExpirationAction.DESTROY);
        factory.setEntryIdleTimeout(expire);
        System.setProperty(LocalRegion.EXPIRY_MS_PROPERTY, "true");
        try {
          Region<Object, Object> region = createRegion(name, factory.create());
          region.create(key, value);
        } finally {
          System.getProperties().remove(LocalRegion.EXPIRY_MS_PROPERTY);
        }
      }
    };

    vm1.invoke(create);

    // vm0 - Create region, short timeout
    vm0.invoke(new CacheSerializableRunnable("Create with IdleTimeout") {
      @Override
      public void run2() throws CacheException {
        RegionAttributes<?, ?> ra = getRegionAttributes();
        AttributesFactory<?, ?> factory = new AttributesFactory<>(ra);
        final boolean partitioned =
            ra.getPartitionAttributes() != null || ra.getDataPolicy().withPartitioning();
        // MUST be nonmirrored, so turn off persistBackup if this is a disk region test
        if (!partitioned) {
          if (ra.getEvictionAttributes() == null
              || !ra.getEvictionAttributes().getAction().isOverflowToDisk()) {
            factory.setDiskStoreName(null);
          }
          factory.setDataPolicy(DataPolicy.NORMAL);
        }
        factory.setStatisticsEnabled(true);
        ExpirationAttributes expire =
            new ExpirationAttributes(shortTimeout, ExpirationAction.DESTROY);
        factory.setEntryIdleTimeout(expire);
        System.setProperty(LocalRegion.EXPIRY_MS_PROPERTY, "true");
        try {
          createRegion(name, factory.create());
        } finally {
          System.getProperties().remove(LocalRegion.EXPIRY_MS_PROPERTY);
        }
      }
    });

    Wait.pause(shortTimeout * 2);

    // Even though netSearch finds vm1's entry is not expired, it is considered
    // expired with respect to vm0's attributes
    vm0.invoke(new CacheSerializableRunnable("get(key), expect null") {
      @Override
      public void run2() throws CacheException {
        Region<Object, Object> region = getRootRegion().getSubregion(name);
        Object got = region.get(key);
        assertThat(got).isNull();
      }
    });

    // We see the object is actually still there
    vm1.invoke(new CacheSerializableRunnable("get(key), expect value") {
      @Override
      public void run2() throws CacheException {
        Region<Object, Object> region = getRootRegion().getSubregion(name);
        Object got = region.get(key);
        assertThat(got).isEqualTo(value);
      }
    });
  }

  private static TestCacheListener<Object, Object> destroyListener = null;

  /**
   * Tests that an entry in a distributed region that expires with a distributed destroy causes an
   * event in other VM with isExpiration flag set.
   */
  @Test
  public void testEntryTtlDestroyEvent() {
    assumeThat(getRegionAttributes().getPartitionAttributes())
        .withFailMessage("the region has partition attributes").isNull();

    final String name = this.getUniqueName();
    final int timeout = 22; // ms
    final Object key = "KEY";
    final Object value = "VALUE";

    VM vm0 = VM.getVM(0);
    VM vm1 = VM.getVM(1);

    class DestroyListener extends TestCacheListener<Object, Object> {
      boolean eventIsExpiration = false;

      @Override
      public void afterDestroyBeforeAddEvent(EntryEvent<Object, Object> event) {
        eventIsExpiration = event.getOperation().isExpiration();
      }

      @Override
      public void afterDestroy2(EntryEvent<Object, Object> event) {
        if (event.isOriginRemote()) {
          assertThat(event.getDistributedMember().equals(getSystem().getDistributedMember()))
              .isFalse();
        } else {
          assertThat(event.getDistributedMember()).isEqualTo(
              getSystem().getDistributedMember());
        }
        assertThat(event.getOperation()).isEqualTo(Operation.EXPIRE_DESTROY);
        assertThat(event.getOldValue()).isEqualTo(value);
        eventIsExpiration = event.getOperation().isExpiration();
      }

      @Override
      public void afterCreate2(EntryEvent<Object, Object> ignored) {}

      @Override
      public void afterUpdate2(EntryEvent<Object, Object> ignored) {}
    }

    SerializableRunnable createRegion = new CacheSerializableRunnable("Create with Listener") {
      @Override
      public void run2() throws CacheException {
        AttributesFactory<Object, Object> fac = new AttributesFactory<>(getRegionAttributes());
        fac.addCacheListener(destroyListener = new DestroyListener());
        createRegion(name, fac.create());
      }
    };

    vm1.invoke(createRegion);

    vm0.invoke(new CacheSerializableRunnable("Create with TTL") {
      @Override
      public void run2() throws CacheException {
        AttributesFactory<?, ?> factory = new AttributesFactory<>(getRegionAttributes());
        factory.setStatisticsEnabled(true);
        ExpirationAttributes expire = new ExpirationAttributes(timeout, ExpirationAction.DESTROY);
        factory.setEntryTimeToLive(expire);
        if (!getRegionAttributes().getDataPolicy().withReplication()) {
          factory.setDataPolicy(DataPolicy.NORMAL);
          factory.setSubscriptionAttributes(new SubscriptionAttributes(InterestPolicy.ALL));
        }
        System.setProperty(LocalRegion.EXPIRY_MS_PROPERTY, "true");
        try {
          createRegion(name, factory.create());
          ExpiryTask.suspendExpiration();
          // suspend to make sure we can see that the put is distributed to this member
        } finally {
          System.getProperties().remove(LocalRegion.EXPIRY_MS_PROPERTY);
        }
      }
    });

    try {

      // let region create finish before doing put
      // pause(10);

      vm1.invoke(new SerializableCallable<Object>() {
        @Override
        public Object call() {
          Region<Object, Object> region = getRootRegion().getSubregion(name);
          DestroyListener dl = (DestroyListener) region.getAttributes().getCacheListeners()[0];
          dl.enableEventHistory();
          region.put(key, value);
          // reset listener after create event
          assertThat(dl.wasInvoked()).isTrue();
          List<CacheEvent<Object, Object>> history = dl.getEventHistory();
          CacheEvent<Object, Object> ce = history.get(0);
          dl.disableEventHistory();
          assertThat(ce.getOperation()).isEqualTo(Operation.CREATE);
          return null;
        }
      });
      vm0.invoke(new CacheSerializableRunnable("Check create received from vm1") {
        @Override
        public void run2() throws CacheException {
          final Region<Object, Object> region = getRootRegion().getSubregion(name);
          await("never saw create of " + key)
              .until(() -> region.getEntry(key) != null);
        }
      });

    } finally {
      vm0.invoke(new CacheSerializableRunnable("resume expiration") {
        @Override
        public void run2() throws CacheException {
          ExpiryTask.permitExpiration();
        }
      });
    }

    // now wait for it to expire
    vm0.invoke(new CacheSerializableRunnable("Check local destroy") {
      @Override
      public void run2() throws CacheException {
        final Region<Object, Object> region = getRootRegion().getSubregion(name);
        await("never saw expire of " + key)
            .until(() -> region.getEntry(key) == null);
      }
    });

    vm1.invoke(new CacheSerializableRunnable("Verify destroyed and event") {
      @Override
      public void run2() throws CacheException {
        final Region<Object, Object> region = getRootRegion().getSubregion(name);
        await("never saw expire of " + key)
            .until(() -> region.getEntry(key) == null);

        assertThat(destroyListener.waitForInvocation(555)).isTrue();
        assertThat(((DestroyListener) destroyListener).eventIsExpiration).isTrue();
      }
    });
  }

  /**
   * Tests that an entry in a distributed region expires with a local destroy after a given time to
   * live.
   */
  @Test
  public void testEntryTtlLocalDestroy() throws Exception {
    assumeThat(getRegionAttributes().getPartitionAttributes())
        .withFailMessage("the region has partition attributes").isNull();

    final boolean mirrored = getRegionAttributes().getDataPolicy().withReplication();
    final boolean partitioned = getRegionAttributes().getPartitionAttributes() != null
        || getRegionAttributes().getDataPolicy().withPartitioning();
    if (!mirrored) {
      // This test fails intermittently because the DSClock we inherit from the existing
      // distributed system is stuck in the "stopped" state.
      // The DSClock is going away when java groups is merged and at that
      // time this following can be removed.
      disconnectAllFromDS();
    }

    final String name = this.getUniqueName();
    final int timeout = 10; // ms
    final String key = "KEY";
    final String value = "VALUE";

    VM vm0 = VM.getVM(0);
    VM vm1 = VM.getVM(1);

    SerializableRunnable create = new CacheSerializableRunnable("Populate") {
      @Override
      public void run2() throws CacheException {
        System.setProperty(LocalRegion.EXPIRY_MS_PROPERTY, "true");
        try {
          createRegion(name);
        } finally {
          System.getProperties().remove(LocalRegion.EXPIRY_MS_PROPERTY);
        }
      }
    };

    vm1.invoke(create);

    vm0.invoke(new CacheSerializableRunnable("Create with TTL") {
      @Override
      public void run2() throws CacheException {
        AttributesFactory<Object, Object> factory = new AttributesFactory<>(getRegionAttributes());
        factory.setStatisticsEnabled(true);
        ExpirationAttributes expire =
            new ExpirationAttributes(timeout, ExpirationAction.LOCAL_DESTROY);
        factory.setEntryTimeToLive(expire);
        if (!mirrored) {
          // make it cached all events so that remote creates will also
          // be created here
          if (!partitioned) {
            factory.setDataPolicy(DataPolicy.NORMAL);
          }
          factory.setSubscriptionAttributes(new SubscriptionAttributes(InterestPolicy.ALL));
          factory.addCacheListener(new CountingDistCacheListener<>());
        }
        // Crank up the expiration so test runs faster. This property only needs to be set while the
        // region is created
        System.setProperty(LocalRegion.EXPIRY_MS_PROPERTY, "true");
        try {
          createRegion(name, factory.create());
          if (mirrored) {
            fail("Should have thrown an IllegalStateException");
          }
        } catch (IllegalStateException e) {
          if (!mirrored) {
            throw e;
          }
        } finally {
          System.getProperties().remove(LocalRegion.EXPIRY_MS_PROPERTY);
        }
      }
    });
    if (mirrored) {
      return;
    }

    vm1.invoke(new SerializableCallable<Object>() {
      @Override
      public Object call() {
        Region<Object, Object> region = getRootRegion().getSubregion(name);
        region.put(key, value);
        return null;
      }
    });

    vm0.invoke(new CacheSerializableRunnable("Check local destroy") {
      @Override
      public void run2() throws CacheException {
        final Region<Object, Object> region = getRootRegion().getSubregion(name);
        // make sure we created the entry
        CountingDistCacheListener<Object, Object> l =
            (CountingDistCacheListener<Object, Object>) region.getAttributes()
                .getCacheListeners()[0];
        await()
            .untilAsserted(() -> l.assertCount(1, 0, 0, 0));

        // now make sure it expires
        // this should happen really fast since timeout is 10 ms.
        // But it may take longer in some cases because of thread
        // scheduling delays and machine load (see GEODE-410).
        // The previous code would fail after 100ms; now we wait 3000ms.

        try {
          await()
              .until(() -> {
                Region.Entry re = region.getEntry(key);
                if (re != null) {
                  EntryExpiryTask eet = getEntryExpiryTask(region, key);
                  if (eet != null) {
                    long stopTime =
                        getCache().getInternalDistributedSystem().getClock().getStopTime();
                    logger.info("DEBUG: waiting for expire destroy expirationTime= "
                        + eet.getExpirationTime() + " now=" + eet.calculateNow() + " stopTime="
                        + stopTime + " currentTimeMillis=" + System.currentTimeMillis());
                  } else {
                    logger.info("DEBUG: waiting for expire destroy but expiry task is null");
                  }
                }
                return re == null;
              });
        } catch (ConditionTimeoutException timeout) {
          // Catching in order to inform about the final state
          fail(determineExpiryFailureMessage(region, key), timeout);
        }

        assertThat(region.getEntry(key)).isNull();
      }
    });

    vm1.invoke(new CacheSerializableRunnable("Verify local") {
      @Override
      public void run2() throws CacheException {
        Region<Object, Object> region = getRootRegion().getSubregion(name);
        Region.Entry entry = region.getEntry(key);
        assertThat(entry.getValue()).isEqualTo(value);
      }
    });
  }

  private String determineExpiryFailureMessage(Region region, String key) {
    String expiryInfo = "";
    try {
      EntryExpiryTask eet = getEntryExpiryTask(region, key);
      if (eet != null) {
        expiryInfo = "expirationTime= " + eet.getExpirationTime()
            + " now=" + eet.calculateNow()
            + " currentTimeMillis=" + System.currentTimeMillis();
      }
    } catch (EntryNotFoundException ex) {
      expiryInfo = "EntryNotFoundException when getting expiry task";
    }
    return "Entry for key " + key + " never expired (since it still exists) "
        + expiryInfo;
  }

  private static EntryExpiryTask getEntryExpiryTask(Region r, Object key) {
    EntryExpiryTask result = null;
    try {
      LocalRegion lr = (LocalRegion) r;
      result = lr.getEntryExpiryTask(key);
    } catch (EntryNotFoundException ignore) {
    }
    return result;
  }

  /**
   * Tests to makes sure that a distributed update resets the expiration timer.
   */
  @Test
  public void testUpdateResetsIdleTime() {
    final String name = this.getUniqueName();
    // test no longer waits for this timeout to expire
    final int timeout = 90; // seconds
    final Object key = "KEY";
    final Object value = "VALUE";

    VM vm0 = VM.getVM(0);
    VM vm1 = VM.getVM(1);

    vm0.invoke(new CacheSerializableRunnable("Create with Idle") {
      @Override
      public void run2() throws CacheException {
        AttributesFactory<Object, Object> factory = new AttributesFactory<>(getRegionAttributes());
        factory.setStatisticsEnabled(true);
        ExpirationAttributes expire = new ExpirationAttributes(timeout, ExpirationAction.DESTROY);
        factory.setEntryIdleTimeout(expire);
        LocalRegion region = (LocalRegion) createRegion(name, factory.create());
        if (region.getDataPolicy().withPartitioning()) {
          // Force all buckets to be created locally so the
          // test will know that the create happens in this vm
          // and the update (in vm1) is remote.
          PartitionRegionHelper.assignBucketsToPartitions(region);
        }
        region.create(key, null);
        EntryExpiryTask eet = region.getEntryExpiryTask(key);
        region.create("createExpiryTime", eet.getExpirationTime());
        Wait.waitForExpiryClockToChange(region);
      }
    });

    vm1.invoke(new CacheSerializableRunnable("Create Region " + name) {
      @Override
      public void run2() throws CacheException {
        AttributesFactory<?, ?> factory = new AttributesFactory<>(getRegionAttributes());
        factory.setStatisticsEnabled(true);
        ExpirationAttributes expire = new ExpirationAttributes(timeout, ExpirationAction.DESTROY);
        factory.setEntryIdleTimeout(expire);
        if (getRegionAttributes().getPartitionAttributes() != null) {
          createRegion(name, factory.create());
        } else {
          createRegion(name);
        }
      }
    });

    vm1.invoke(new CacheSerializableRunnable("Update entry") {
      @Override
      public void run2() throws CacheException {
        final Region<Object, Object> r = getRootRegion().getSubregion(name);
        assertThat(r).isNotNull();
        r.put(key, value);
      }
    });

    vm0.invoke(new CacheSerializableRunnable("Verify reset") {
      @Override
      public void run2() throws CacheException {
        final LocalRegion region = (LocalRegion) getRootRegion().getSubregion(name);

        // wait for update to reach us from vm1 (needed if no-ack)
        await("never saw key " + key + "equal to value " + value)
            .until(() -> value.equals(region.get(key)));

        EntryExpiryTask eet = region.getEntryExpiryTask(key);
        long createExpiryTime = (Long) region.get("createExpiryTime");
        long updateExpiryTime = eet.getExpirationTime();
        if (updateExpiryTime - createExpiryTime <= 0L) {
          fail("update did not reset the expiration time. createExpiryTime=" + createExpiryTime
              + " updateExpiryTime=" + updateExpiryTime);
        }
      }
    });
  }

  private static final int NB1_CHUNK_SIZE = 500 * 1024; // ==
  // InitialImageOperation.CHUNK_SIZE_IN_BYTES
  private static final int NB1_NUM_ENTRIES = 1000;
  private static final int NB1_VALUE_SIZE = NB1_CHUNK_SIZE * 10 / NB1_NUM_ENTRIES;

  /**
   * Tests that distributed ack operations do not block while another cache is doing a
   * getInitialImage.
   */
  @Test
  public void testNonblockingGetInitialImage() {
    assumeThat(supportsReplication()).isTrue();
    // don't run this test if global scope since its too difficult to predict
    // how many concurrent operations will occur
    assumeThat(getRegionAttributes().getScope().isGlobal()).isFalse();

    final String name = this.getUniqueName();
    final byte[][] values = new byte[NB1_NUM_ENTRIES][];

    for (int i = 0; i < NB1_NUM_ENTRIES; i++) {
      values[i] = new byte[NB1_VALUE_SIZE];
      Arrays.fill(values[i], (byte) 0x42);
    }

    VM vm0 = VM.getVM(0);
    VM vm2 = VM.getVM(2);

    SerializableRunnable create = new CacheSerializableRunnable("Create Mirrored Region") {
      @Override
      public void run2() throws CacheException {
        beginCacheXml();
        { // root region must be DACK because its used to sync up async subregions
          AttributesFactory<?, ?> factory = new AttributesFactory<>();
          factory.setScope(Scope.DISTRIBUTED_ACK);
          factory.setDataPolicy(DataPolicy.NORMAL);
          factory.setSubscriptionAttributes(new SubscriptionAttributes(InterestPolicy.ALL));
          logger.info("MJT DEBUG: attrs0 are " + factory.create());
          createRootRegion(factory.create());
        }
        {
          AttributesFactory<?, ?> factory = new AttributesFactory<>(getRegionAttributes());
          factory.setSubscriptionAttributes(new SubscriptionAttributes(InterestPolicy.ALL));
          if (getRegionAttributes().getDataPolicy() == DataPolicy.NORMAL) {
            factory.setDataPolicy(DataPolicy.PRELOADED);
          }
          logger.info("MJT DEBUG: attrs1 are " + factory.create());
          createRegion(name, factory.create());
        }
        finishCacheXml(name);
        // reset slow
        org.apache.geode.internal.cache.InitialImageOperation.slowImageProcessing = 0;
      }
    };

    vm0.invoke(new CacheSerializableRunnable("Create Nonmirrored Region") {
      @Override
      public void run2() throws CacheException {
        { // root region must be DACK because its used to sync up async subregions
          AttributesFactory<?, ?> factory = new AttributesFactory<>();
          factory.setScope(Scope.DISTRIBUTED_ACK);
          factory.setDataPolicy(DataPolicy.EMPTY);
          createRootRegion(factory.create());
        }
        {
          AttributesFactory<?, ?> factory = new AttributesFactory<>(getRegionAttributes());
          createRegion(name, factory.create());
        }
        // reset slow
        org.apache.geode.internal.cache.InitialImageOperation.slowImageProcessing = 0;
      }
    });

    vm0.invoke(new CacheSerializableRunnable("Put initial data") {
      @Override
      public void run2() throws CacheException {
        Region<Integer, byte[]> region = getRootRegion().getSubregion(name);
        for (int i = 0; i < NB1_NUM_ENTRIES; i++) {
          region.put(i, values[i]);
        }
        assertThat(region.keySet().size()).isEqualTo(NB1_NUM_ENTRIES);
      }
    });

    // start asynchronous process that does updates to the data
    AsyncInvocation async =
        vm0.invokeAsync(new CacheSerializableRunnable("Do Nonblocking Operations") {
          @Override
          public void run2() throws CacheException {
            Region<Object, Object> region = getRootRegion().getSubregion(name);

            // wait for profile of getInitialImage cache to show up
            final org.apache.geode.internal.cache.CacheDistributionAdvisor adv =
                ((org.apache.geode.internal.cache.DistributedRegion) region)
                    .getCacheDistributionAdvisor();
            final int expectedProfiles = 1;

            await("replicate count never reached " + expectedProfiles)
                .until(() -> {
                  DataPolicy currentPolicy = getRegionAttributes().getDataPolicy();
                  if (currentPolicy == DataPolicy.PRELOADED) {
                    return (adv.advisePreloadeds().size()
                        + adv.adviseReplicates().size()) >= expectedProfiles;
                  } else {
                    return adv.adviseReplicates().size() >= expectedProfiles;
                  }
                });

            DataPolicy currentPolicy = getRegionAttributes().getDataPolicy();
            int numProfiles;
            if (currentPolicy == DataPolicy.PRELOADED) {
              numProfiles = adv.advisePreloadeds().size() + adv.adviseReplicates().size();
            } else {
              numProfiles = adv.adviseReplicates().size();
            }
            assertThat(numProfiles >= expectedProfiles).isTrue();

            // operate on every odd entry with different value, alternating between
            // updates, invalidates, and destroys. These operations are likely
            // to be nonblocking if a sufficient number of updates get through
            // before the get initial image is complete.
            for (int i = 1; i < NB1_NUM_ENTRIES; i += 2) {
              Object key = i;
              logger.info("Operation #" + i + " on key " + key);
              switch (i % 6) {
                case 1: // UPDATE
                  // use the current timestamp so we know when it happened
                  // we could have used last modification timestamps, but
                  // this works without enabling statistics
                  Object value = System.currentTimeMillis();
                  region.put(key, value);
                  // no longer safe since get is not allowed to member doing GII
                  // if (getRegionAttributes().getScope().isDistributedAck()) {
                  // // do a nonblocking netSearch
                  // region.localInvalidate(key);
                  // assertIndexDetailsEquals(value, region.get(key));
                  // }
                  break;
                case 3: // INVALIDATE
                  region.invalidate(key);
                  if (getRegionAttributes().getScope().isDistributedAck()) {
                    // do a nonblocking netSearch
                    assertThat(region.get(key)).isNull();
                  }
                  break;
                case 5: // DESTROY
                  region.destroy(key);
                  if (getRegionAttributes().getScope().isDistributedAck()) {
                    // do a nonblocking netSearch
                    assertThat(region.get(key)).isNull();
                  }
                  break;
                default:
                  fail("unexpected modulus result: " + i);
                  break;
              }
            }

            // add some new keys
            for (int i = NB1_NUM_ENTRIES; i < NB1_NUM_ENTRIES + 200; i++) {
              region.create(i, System.currentTimeMillis());
            }
            // now do a put and our DACK root region which will not complete
            // until processed on otherside which means everything done before this
            // point has been processed
            getRootRegion().put("DONE", "FLUSH_OPS");
          }
        });

    // in the meantime, do the get initial image in vm2
    // slow down image processing to make it more likely to get async updates
    if (!getRegionAttributes().getScope().isGlobal()) {
      vm2.invoke(new SerializableRunnable("Set slow image processing") {
        @Override
        public void run() {
          // if this is a no_ack test, then we need to slow down more because of the
          // pauses in the nonblocking operations
          org.apache.geode.internal.cache.InitialImageOperation.slowImageProcessing = 200;
        }
      });
    }

    logger.info("Before GetInitialImage, data policy is " + getRegionAttributes().getDataPolicy()
        + ", scope is " + getRegionAttributes().getScope());
    AsyncInvocation asyncGII = vm2.invokeAsync(create);

    if (!getRegionAttributes().getScope().isGlobal()) {
      // wait for nonblocking operations to complete
      ThreadUtils.join(async, 30 * 1000);
      vm2.invoke(new SerializableRunnable("Set fast image processing") {
        @Override
        public void run() {
          org.apache.geode.internal.cache.InitialImageOperation.slowImageProcessing = 0;
        }
      });
      logger.info("after async nonblocking ops complete");
    }

    // wait for GII to complete
    ThreadUtils.join(asyncGII, 30 * 1000);
    final long iiComplete = System.currentTimeMillis();
    logger.info("Complete GetInitialImage at: " + System.currentTimeMillis());

    if (getRegionAttributes().getScope().isGlobal()) {
      // wait for nonblocking operations to complete
      ThreadUtils.join(async, 30 * 1000);
    }
    if (async.exceptionOccurred()) {
      fail("async failed", async.getException());
    }
    if (asyncGII.exceptionOccurred()) {
      fail("asyncGII failed", asyncGII.getException());
    }

    // Locally destroy the region in vm0 so we know that they are not found by
    // a netSearch
    vm0.invoke(new CacheSerializableRunnable("Locally destroy region") {
      @Override
      public void run2() throws CacheException {
        Region<Object, Object> region = getRootRegion().getSubregion(name);
        region.localDestroyRegion();
      }
    });
    logger.info("after localDestroyRegion");

    // invoke repeating so noack regions wait for all updates to get processed
    vm2.invoke(repeatingIfNecessary(5000,
        new CacheSerializableRunnable("Verify entryCount") {
          boolean entriesDumped = false;

          @Override
          public void run2() throws CacheException {
            Region<Object, Object> region = getRootRegion().getSubregion(name);
            // expected entry count (subtract entries destroyed)
            int entryCount = NB1_NUM_ENTRIES + 200 - NB1_NUM_ENTRIES / 6;
            int actualCount = region.entrySet(false).size();
            if (actualCount == NB1_NUM_ENTRIES + 200) {
              // entries not destroyed, dump entries that were supposed to have been destroyed
              dumpDestroyedEntries(region);
            }
            assertThat(actualCount).isEqualTo(entryCount);
          }

          private void dumpDestroyedEntries(Region region) throws EntryNotFoundException {
            if (entriesDumped) {
              return;
            }
            entriesDumped = true;

            logger.info("DUMPING Entries with values in VM that should have been destroyed:");
            for (int i = 5; i < NB1_NUM_ENTRIES; i += 6) {
              try {
                logger.info(i + "-->" + ((org.apache.geode.internal.cache.LocalRegion) region)
                    .getValueInVM(i));
              } catch (EntryNotFoundException expected) {
                logger.info(i + "-->" + "CORRECTLY DESTROYED");
              }
            }
          }
        }));
    logger.info("after verify entryCount");

    vm2.invoke(new CacheSerializableRunnable("Verify keys/values & Nonblocking") {
      @Override
      public void run2() throws CacheException {
        Region<Object, Object> region = getRootRegion().getSubregion(name);
        // expected entry count (subtract entries destroyed)
        int entryCount = NB1_NUM_ENTRIES + 200 - NB1_NUM_ENTRIES / 6;
        assertThat(region.entrySet(false).size()).isEqualTo(entryCount);
        // determine how many entries were updated before getInitialImage
        // was complete
        int numConcurrent = 0;
        numConcurrent = verifyEntryUpdateCounts(region, numConcurrent, values, iiComplete);
        logger.info(name + ": " + numConcurrent
            + " entries out of " + entryCount + " were updated concurrently with getInitialImage");
        // make sure at least some of them were concurrent
        if (region.getAttributes().getScope().isGlobal()) {
          assertThat(numConcurrent < 10).describedAs(
              "Too many concurrent updates when expected to block: " + numConcurrent).isTrue();
        } else {
          int min = 30;
          assertThat(numConcurrent >= min).describedAs(
              "Not enough updates concurrent with getInitialImage occurred to my liking. "
                  + numConcurrent + " entries out of " + entryCount
                  + " were updated concurrently with getInitialImage, and I'd expect at least "
                  + min
                  + " or so")
              .isTrue();
        }
      }
    });
    logger.info("after verify key/values");
  }

  /**
   * Tests that distributed ack operations do not block while another cache is doing a
   * getInitialImage.
   */
  @Test
  public void testTXNonblockingGetInitialImage() {
    assumeThat(supportsReplication()).isTrue();
    assumeThat(supportsTransactions()).isTrue();
    // don't run this test if global scope since its too difficult to predict
    // how many concurrent operations will occur
    assumeThat(getRegionAttributes().getScope().isGlobal()).isFalse();
    assumeThat(getRegionAttributes().getDataPolicy().withPersistence()).isFalse();

    final String name = this.getUniqueName();
    final byte[][] values = new byte[NB1_NUM_ENTRIES][];

    for (int i = 0; i < NB1_NUM_ENTRIES; i++) {
      values[i] = new byte[NB1_VALUE_SIZE];
      Arrays.fill(values[i], (byte) 0x42);
    }

    VM vm0 = VM.getVM(0);
    VM vm2 = VM.getVM(2);

    SerializableRunnable create = new CacheSerializableRunnable("Create Mirrored Region") {
      @Override
      public void run2() throws CacheException {
        beginCacheXml();
        { // root region must be DACK because its used to sync up async subregions
          AttributesFactory<?, ?> factory = new AttributesFactory<>();
          factory.setScope(Scope.DISTRIBUTED_ACK);
          factory.setDataPolicy(DataPolicy.NORMAL);
          factory.setSubscriptionAttributes(new SubscriptionAttributes(InterestPolicy.ALL));
          createRootRegion(factory.create());
        }
        {
          AttributesFactory<?, ?> factory = new AttributesFactory<>(getRegionAttributes());
          if (getRegionAttributes().getDataPolicy() == DataPolicy.NORMAL) {
            factory.setDataPolicy(DataPolicy.PRELOADED);
          }
          factory.setSubscriptionAttributes(new SubscriptionAttributes(InterestPolicy.ALL));
          createRegion(name, factory.create());
        }
        finishCacheXml(name);
        // reset slow
        org.apache.geode.internal.cache.InitialImageOperation.slowImageProcessing = 0;
      }
    };

    vm0.invoke(new CacheSerializableRunnable("Create Nonmirrored Region") {
      @Override
      public void run2() throws CacheException {
        { // root region must be DACK because its used to sync up async subregions
          AttributesFactory<?, ?> factory = new AttributesFactory<>();
          factory.setScope(Scope.DISTRIBUTED_ACK);
          factory.setDataPolicy(DataPolicy.EMPTY);
          createRootRegion(factory.create());
        }
        {
          AttributesFactory<?, ?> factory = new AttributesFactory<>(getRegionAttributes());
          createRegion(name, factory.create());
        }
        // reset slow
        org.apache.geode.internal.cache.InitialImageOperation.slowImageProcessing = 0;
      }
    });

    vm0.invoke(new CacheSerializableRunnable("Put initial data") {
      @Override
      public void run2() throws CacheException {
        Region<Object, Object> region = getRootRegion().getSubregion(name);
        for (int i = 0; i < NB1_NUM_ENTRIES; i++) {
          region.put(i, values[i]);
        }
        assertThat(region.keySet().size()).isEqualTo(NB1_NUM_ENTRIES);
      }
    });

    // start asynchronous process that does updates to the data
    AsyncInvocation async =
        vm0.invokeAsync(new CacheSerializableRunnable("Do Nonblocking Operations") {
          @Override
          public void run2() throws CacheException {
            Region<Object, Object> region = getRootRegion().getSubregion(name);

            // wait for profile of getInitialImage cache to show up
            final org.apache.geode.internal.cache.CacheDistributionAdvisor adv =
                ((org.apache.geode.internal.cache.DistributedRegion) region)
                    .getCacheDistributionAdvisor();
            final int expectedProfiles = 1;

            await("replicate count never reached " + expectedProfiles)
                .until(() -> {
                  DataPolicy currentPolicy = getRegionAttributes().getDataPolicy();
                  if (currentPolicy == DataPolicy.PRELOADED) {
                    return (adv.advisePreloadeds().size()
                        + adv.adviseReplicates().size()) >= expectedProfiles;
                  } else {
                    return adv.adviseReplicates().size() >= expectedProfiles;
                  }
                });
            // operate on every odd entry with different value, alternating between
            // updates, invalidates, and destroys. These operations are likely
            // to be nonblocking if a sufficient number of updates get through
            // before the get initial image is complete.
            CacheTransactionManager txMgr = getCache().getCacheTransactionManager();
            for (int i = 1; i < NB1_NUM_ENTRIES; i += 2) {
              Object key = i;
              switch (i % 6) {
                case 1: // UPDATE
                  // use the current timestamp so we know when it happened
                  // we could have used last modification timestamps, but
                  // this works without enabling statistics
                  Object value = System.currentTimeMillis();
                  txMgr.begin();
                  region.put(key, value);
                  txMgr.commit();
                  // no longer safe since get is not allowed to member doing GII
                  // if (getRegionAttributes().getScope().isDistributedAck()) {
                  // // do a nonblocking netSearch
                  // region.localInvalidate(key);
                  // assertIndexDetailsEquals(value, region.get(key));
                  // }
                  break;
                case 3: // INVALIDATE
                  txMgr.begin();
                  region.invalidate(key);
                  txMgr.commit();
                  if (getRegionAttributes().getScope().isDistributedAck()) {
                    // do a nonblocking netSearch
                    assertThat(region.get(key)).isNull();
                  }
                  break;
                case 5: // DESTROY
                  txMgr.begin();
                  region.destroy(key);
                  txMgr.commit();
                  if (getRegionAttributes().getScope().isDistributedAck()) {
                    // do a nonblocking netSearch
                    assertThat(region.get(key)).isNull();
                  }
                  break;
                default:
                  fail("unexpected modulus result: " + i);
                  break;
              }
            }
            // add some new keys
            for (int i = NB1_NUM_ENTRIES; i < NB1_NUM_ENTRIES + 200; i++) {
              txMgr.begin();
              region.create(i, System.currentTimeMillis());
              txMgr.commit();
            }
            // now do a put and our DACK root region which will not complete
            // until processed on otherside which means everything done before this
            // point has been processed
            getRootRegion().put("DONE", "FLUSH_OPS");
          }
        });

    // in the meantime, do the get initial image in vm2
    // slow down image processing to make it more likely to get async updates
    if (!getRegionAttributes().getScope().isGlobal()) {
      vm2.invoke(new SerializableRunnable("Set slow image processing") {
        @Override
        public void run() {
          // if this is a no_ack test, then we need to slow down more because of the
          // pauses in the nonblocking operations
          org.apache.geode.internal.cache.InitialImageOperation.slowImageProcessing = 200;
        }
      });
    }

    AsyncInvocation asyncGII = vm2.invokeAsync(create);

    if (!getRegionAttributes().getScope().isGlobal()) {
      // wait for nonblocking operations to complete
      ThreadUtils.join(async, 30 * 1000);

      vm2.invoke(new SerializableRunnable("Set fast image processing") {
        @Override
        public void run() {
          org.apache.geode.internal.cache.InitialImageOperation.slowImageProcessing = 0;
        }
      });
      logger.info("after async nonblocking ops complete");
    }

    // wait for GII to complete
    ThreadUtils.join(asyncGII, 30 * 1000);
    final long iiComplete = System.currentTimeMillis();
    logger.info("Complete GetInitialImage at: " + System.currentTimeMillis());
    if (getRegionAttributes().getScope().isGlobal()) {
      // wait for nonblocking operations to complete
      ThreadUtils.join(async, 30 * 1000);
    }

    if (async.exceptionOccurred()) {
      fail("async failed", async.getException());
    }
    if (asyncGII.exceptionOccurred()) {
      fail("asyncGII failed", asyncGII.getException());
    }

    // Locally destroy the region in vm0 so we know that they are not found by
    // a netSearch
    vm0.invoke(new CacheSerializableRunnable("Locally destroy region") {
      @Override
      public void run2() throws CacheException {
        Region<Object, Object> region = getRootRegion().getSubregion(name);
        region.localDestroyRegion();
      }
    });

    // invoke repeating so noack regions wait for all updates to get processed
    vm2.invoke(repeatingIfNecessary(5000,
        new CacheSerializableRunnable("Verify entryCount") {
          boolean entriesDumped = false;

          @Override
          public void run2() throws CacheException {
            Region<Object, Object> region = getRootRegion().getSubregion(name);
            // expected entry count (subtract entries destroyed)
            int entryCount = NB1_NUM_ENTRIES + 200 - NB1_NUM_ENTRIES / 6;
            int actualCount = region.entrySet(false).size();
            if (actualCount == NB1_NUM_ENTRIES + 200) {
              // entries not destroyed, dump entries that were supposed to have been destroyed
              dumpDestroyedEntries(region);
            }
            assertThat(actualCount).isEqualTo(entryCount);
          }

          private void dumpDestroyedEntries(Region region) throws EntryNotFoundException {
            if (entriesDumped) {
              return;
            }
            entriesDumped = true;

            logger.info("DUMPING Entries with values in VM that should have been destroyed:");
            for (int i = 5; i < NB1_NUM_ENTRIES; i += 6) {
              logger.info(i + "-->" + ((org.apache.geode.internal.cache.LocalRegion) region)
                  .getValueInVM(i));
            }
          }
        }));

    vm2.invoke(new CacheSerializableRunnable("Verify keys/values & Nonblocking") {
      @Override
      public void run2() throws CacheException {
        Region<Object, Object> region = getRootRegion().getSubregion(name);
        // expected entry count (subtract entries destroyed)
        int entryCount = NB1_NUM_ENTRIES + 200 - NB1_NUM_ENTRIES / 6;
        assertThat(region.entrySet(false).size()).isEqualTo(entryCount);
        // determine how many entries were updated before getInitialImage
        // was complete
        int numConcurrent = 0;
        numConcurrent = verifyEntryUpdateCounts(region, numConcurrent, values, iiComplete);
        logger.info(name + ": " + numConcurrent
            + " entries out of " + entryCount + " were updated concurrently with getInitialImage");
        // make sure at least some of them were concurrent
        {
          int min = 30;
          String description =
              "Not enough updates concurrent with getInitialImage occurred to my liking. "
                  + numConcurrent + " entries out of " + entryCount
                  + " were updated concurrently with getInitialImage, and I'd expect at least "
                  + min
                  + " or so";
          assertThat(numConcurrent >= min).describedAs(description).isTrue();
        }
      }
    });
  }

  private int verifyEntryUpdateCounts(Region<Object, Object> region, int numConcurrent,
      byte[][] values, long iiComplete) {
    for (int i = 0; i < NB1_NUM_ENTRIES + 200; i++) {
      Region.Entry entry = region.getEntry(i);
      Object v = entry == null ? null : entry.getValue();
      if (i < NB1_NUM_ENTRIES) { // old keys
        switch (i % 6) {
          // even keys are originals
          case 0:
          case 2:
          case 4:
            assertThat(entry).isNotNull();
            assertThat(Arrays.equals(values[i], (byte[]) v)).isTrue();
            break;
          case 1: // updated
            assertThat(v).isNotNull();
            boolean condition = v instanceof Long;
            assertThat(condition).describedAs(
                "Value for key " + i + " is not a Long, is a " + v.getClass().getName()).isTrue();
            Long timestamp = (Long) entry.getValue();
            if (timestamp < iiComplete) {
              numConcurrent++;
            }
            break;
          case 3: // invalidated
            assertThat(entry).isNotNull();
            assertThat(v).describedAs("Expected value for " + i + " to be null, but was " + v)
                .isNull();
            break;
          case 5: // destroyed
            assertThat(entry).isNull();
            break;
          default:
            fail("unexpected modulus result: " + (i % 6));
            break;
        }
      } else { // new keys
        assertThat(v).isNotNull();
        boolean condition = v instanceof Long;
        assertThat(condition).describedAs(
            "Value for key " + i + " is not a Long, is a " + v.getClass().getName()).isTrue();
        Long timestamp = (Long) entry.getValue();
        if (timestamp < iiComplete) {
          numConcurrent++;
        }
      }
    }
    return numConcurrent;
  }

  @Ignore("TODO: test is disabled for 51542")
  @Test
  public void testNBRegionInvalidationDuringGetInitialImage() throws Exception {
    assumeThat(supportsReplication()).isTrue();

    disconnectAllFromDS();

    // don't run this for noAck, too many race conditions
    if (getRegionAttributes().getScope().isDistributedNoAck()) {
      return;
    }

    final String name = this.getUniqueName();
    final byte[][] values = new byte[NB1_NUM_ENTRIES][];

    for (int i = 0; i < NB1_NUM_ENTRIES; i++) {
      values[i] = new byte[NB1_VALUE_SIZE];
      Arrays.fill(values[i], (byte) 0x42);
    }

    VM vm0 = VM.getVM(0);
    VM vm2 = VM.getVM(2);

    SerializableRunnable create = new CacheSerializableRunnable("Create Mirrored Region") {
      @Override
      public void run2() throws CacheException {
        beginCacheXml();
        { // root region must be DACK because its used to sync up async subregions
          AttributesFactory<?, ?> factory = new AttributesFactory<>();
          factory.setScope(Scope.DISTRIBUTED_ACK);
          factory.setDataPolicy(DataPolicy.NORMAL);
          factory.setSubscriptionAttributes(new SubscriptionAttributes(InterestPolicy.ALL));
          createRootRegion(factory.create());
        }
        {
          AttributesFactory<?, ?> factory = new AttributesFactory<>(getRegionAttributes());
          factory.setDataPolicy(DataPolicy.REPLICATE);
          createRegion(name, factory.create());
        }
        finishCacheXml(name);
        // reset slow
        org.apache.geode.internal.cache.InitialImageOperation.slowImageProcessing = 0;
      }
    };

    vm0.invoke(new CacheSerializableRunnable("Create Nonmirrored Region") {
      @Override
      public void run2() throws CacheException {
        { // root region must be DACK because its used to sync up async subregions
          AttributesFactory<?, ?> factory = new AttributesFactory<>();
          factory.setScope(Scope.DISTRIBUTED_ACK);
          factory.setDataPolicy(DataPolicy.EMPTY);
          createRootRegion(factory.create());
        }
        {
          AttributesFactory<?, ?> factory = new AttributesFactory<>(getRegionAttributes());
          factory.setDataPolicy(DataPolicy.REPLICATE);
          createRegion(name, factory.create());
        }
        // reset slow
        org.apache.geode.internal.cache.InitialImageOperation.slowImageProcessing = 0;
      }
    });

    vm0.invoke(new CacheSerializableRunnable("Put initial data") {
      @Override
      public void run2() throws CacheException {
        Region<Integer, byte[]> region = getRootRegion().getSubregion(name);
        for (int i = 0; i < NB1_NUM_ENTRIES; i++) {
          region.put(i, values[i]);
        }
        assertThat(region.keySet().size()).isEqualTo(NB1_NUM_ENTRIES);
      }
    });

    // start asynchronous process that does updates to the data
    AsyncInvocation async =
        vm0.invokeAsync(new CacheSerializableRunnable("Do Nonblocking Operations") {
          @Override
          public void run2() throws CacheException {
            Region<Object, Object> region = getRootRegion().getSubregion(name);

            // wait for profile of getInitialImage cache to show up
            final org.apache.geode.internal.cache.CacheDistributionAdvisor adv =
                ((org.apache.geode.internal.cache.DistributedRegion) region)
                    .getCacheDistributionAdvisor();
            final int expectedProfiles = 1;

            await("profile count never reached " + expectedProfiles)
                .until(() -> adv.adviseReplicates().size(), greaterThanOrEqualTo(expectedProfiles));

            // operate on every odd entry with different value, alternating between
            // updates, invalidates, and destroys. These operations are likely
            // to be nonblocking if a sufficient number of updates get through
            // before the get initial image is complete.
            for (int i = 1; i < NB1_NUM_ENTRIES; i += 2) {

              // at magical number 301, do a region invalidation, then continue
              // as before
              if (i == 301) {
                // wait for previous updates to be processed
                flushIfNecessary(region);
                region.invalidateRegion();
                flushIfNecessary(region);
              }

              Object key = i;
              switch (i % 6) {
                case 1: // UPDATE
                  // use the current timestamp so we know when it happened
                  // we could have used last modification timestamps, but
                  // this works without enabling statistics
                  Object value = System.currentTimeMillis();
                  region.put(key, value);
                  break;
                case 3: // INVALIDATE
                  region.invalidate(key);
                  if (getRegionAttributes().getScope().isDistributedAck()) {
                    // do a nonblocking netSearch
                    value = region.get(key);
                    assertThat(value).describedAs(
                        "Expected null value for key: " + i + " but got " + value).isNull();
                  }
                  break;
                case 5: // DESTROY
                  region.destroy(key);
                  if (getRegionAttributes().getScope().isDistributedAck()) {
                    // do a nonblocking netSearch
                    assertThat(region.get(key)).isNull();
                  }
                  break;
                default:
                  fail("unexpected modulus result: " + i);
                  break;
              }
            }
            // now do a put and our DACK root region which will not complete
            // until processed on otherside which means everything done before this
            // point has been processed
            getRootRegion().put("DONE", "FLUSH_OPS");
          }
        });

    // in the meantime, do the get initial image in vm2
    // slow down image processing to make it more likely to get async updates
    if (!getRegionAttributes().getScope().isGlobal()) {
      vm2.invoke(new SerializableRunnable("Set slow image processing") {
        @Override
        public void run() {
          // make sure the cache is set up before turning on slow
          // image processing
          getRootRegion();
          // if this is a no_ack test, then we need to slow down more because of the
          // pauses in the nonblocking operations
          org.apache.geode.internal.cache.InitialImageOperation.slowImageProcessing = 100;
        }
      });
    }

    AsyncInvocation asyncGII = vm2.invokeAsync(create);

    if (!getRegionAttributes().getScope().isGlobal()) {
      // wait for nonblocking operations to complete
      try {
        ThreadUtils.join(async, 30 * 1000);
      } finally {
        vm2.invoke(new SerializableRunnable("Set fast image processing") {
          @Override
          public void run() {
            org.apache.geode.internal.cache.InitialImageOperation.slowImageProcessing = 0;
          }
        });
      }
      logger.info("after async nonblocking ops complete");
    }

    // wait for GII to complete
    ThreadUtils.join(asyncGII, 30 * 1000);
    final long iiComplete = System.currentTimeMillis();
    logger.info("Complete GetInitialImage at: " + System.currentTimeMillis());
    if (getRegionAttributes().getScope().isGlobal()) {
      // wait for nonblocking operations to complete
      ThreadUtils.join(async, 30 * 1000);
    }
    if (asyncGII.exceptionOccurred()) {
      throw new Error("asyncGII failed", asyncGII.getException());
    }
    if (async.exceptionOccurred()) {
      throw new Error("async failed", async.getException());
    }

    // Locally destroy the region in vm0 so we know that they are not found by
    // a netSearch
    vm0.invoke(new CacheSerializableRunnable("Locally destroy region") {
      @Override
      public void run2() throws CacheException {
        Region<Object, Object> region = getRootRegion().getSubregion(name);
        region.localDestroyRegion();
      }
    });

    // invoke repeating so noack regions wait for all updates to get processed
    vm2.invoke(repeatingIfNecessary(3000,
        new CacheSerializableRunnable("Verify entryCount") {
          private boolean entriesDumped = false;

          @Override
          public void run2() throws CacheException {
            Region<Object, Object> region = getRootRegion().getSubregion(name);
            // expected entry count (subtract entries destroyed)
            int entryCount = NB1_NUM_ENTRIES - NB1_NUM_ENTRIES / 6;
            int actualCount = region.entrySet(false).size();
            if (actualCount == NB1_NUM_ENTRIES) {
              // entries not destroyed, dump entries that were supposed to have been destroyed
              dumpDestroyedEntries(region);
            }
            assertThat(actualCount).isEqualTo(entryCount);
          }

          private void dumpDestroyedEntries(Region region) throws EntryNotFoundException {
            if (entriesDumped) {
              return;
            }
            entriesDumped = true;

            logger.info("DUMPING Entries with values in VM that should have been destroyed:");
            for (int i = 5; i < NB1_NUM_ENTRIES; i += 6) {
              logger.info(i + "-->" + ((org.apache.geode.internal.cache.LocalRegion) region)
                  .getValueInVM(i));
            }
          }
        }));

    vm2.invoke(new CacheSerializableRunnable("Verify keys/values & Nonblocking") {
      @Override
      public void run2() throws CacheException {
        Region<Integer, Object> region = getRootRegion().getSubregion(name);
        // expected entry count (subtract entries destroyed)
        int entryCount = NB1_NUM_ENTRIES - NB1_NUM_ENTRIES / 6;
        assertThat(region.entrySet(false).size()).isEqualTo(entryCount);
        // determine how many entries were updated before getInitialImage
        // was complete
        int numConcurrent = 0;

        for (int i = 0; i < NB1_NUM_ENTRIES; i++) {
          Region.Entry entry = region.getEntry(i);
          if (i < 301) {
            if (i % 6 == 5) {
              // destroyed
              assertThat(entry).describedAs(
                  "Expected entry for " + i + " to be destroyed but it is " + entry).isNull();
            } else {
              assertThat(entry).isNotNull();
              Object v = entry.getValue();
              assertThat(v).describedAs("Expected value for " + i + " to be null, but was " + v)
                  .isNull();
            }
          } else {
            Object v = entry == null ? null : entry.getValue();
            switch (i % 6) {
              // even keys are originals
              case 0:
              case 2:
              case 4:
                assertThat(entry).isNotNull();
                assertThat(v).describedAs("Expected value for " + i + " to be null, but was " + v)
                    .isNull();
                break;
              case 1: // updated
                assertThat(entry).describedAs("Expected to find an entry for #" + i).isNotNull();
                assertThat(v).describedAs("Expected to find a value for #" + i).isNotNull();
                boolean condition = v instanceof Long;
                assertThat(condition).describedAs(
                    "Value for key " + i + " is not a Long, is a " + v.getClass().getName())
                    .isTrue();
                Long timestamp = (Long) entry.getValue();
                if (timestamp < iiComplete) {
                  numConcurrent++;
                }
                break;
              case 3: // invalidated
                assertThat(entry).describedAs("Expected to find an entry for #" + i).isNotNull();
                assertThat(v).describedAs("Expected value for " + i + " to be null, but was " + v)
                    .isNull();
                break;
              case 5: // destroyed
                assertThat(entry).describedAs("Expected to not find an entry for #" + i).isNull();
                break;
              default:
                fail("unexpected modulus result: " + (i % 6));
                break;
            }
          }
        }
        logger.info(name + ": " + numConcurrent
            + " entries out of " + entryCount + " were updated concurrently with getInitialImage");

        // [sumedh] Occasionally fails. Do these assertions really make sense?
        // Looks like some random expectations that will always be a hit/miss.

        // make sure at least some of them were concurrent
        if (getRegionAttributes().getScope().isGlobal()) {
          assertThat(numConcurrent < 300).describedAs(
              "Too many concurrent updates when expected to block: " + numConcurrent).isTrue();
        } else {
          assertThat(numConcurrent >= 30).describedAs(
              "Not enough updates concurrent with getInitialImage occurred to my liking. "
                  + numConcurrent + " entries out of " + entryCount
                  + " were updated concurrently with getInitialImage, and I'd expect at least 50 or so")
              .isTrue();
        }
      }
    });
  }

  @Test
  public void testNBRegionDestructionDuringGetInitialImage() {
    assumeThat(supportsReplication()).isTrue();

    final String name = this.getUniqueName();
    final byte[][] values = new byte[NB1_NUM_ENTRIES][];

    for (int i = 0; i < NB1_NUM_ENTRIES; i++) {
      values[i] = new byte[NB1_VALUE_SIZE];
      Arrays.fill(values[i], (byte) 0x42);
    }

    VM vm0 = VM.getVM(0);
    VM vm2 = VM.getVM(2);

    vm0.invoke(new CacheSerializableRunnable("Create Nonmirrored Region") {
      @Override
      public void run2() throws CacheException {
        { // root region must be DACK because its used to sync up async subregions
          AttributesFactory<?, ?> factory = new AttributesFactory<>();
          factory.setScope(Scope.DISTRIBUTED_ACK);
          factory.setDataPolicy(DataPolicy.EMPTY);
          createRootRegion(factory.create());
        }
        {
          AttributesFactory<?, ?> factory = new AttributesFactory<>(getRegionAttributes());
          createRegion(name, factory.create());
        }
        // reset slow
        org.apache.geode.internal.cache.InitialImageOperation.slowImageProcessing = 0;
      }
    });

    vm0.invoke(new CacheSerializableRunnable("Put initial data") {
      @Override
      public void run2() throws CacheException {
        Region<Integer, byte[]> region = getRootRegion().getSubregion(name);
        for (int i = 0; i < NB1_NUM_ENTRIES; i++) {
          region.put(i, values[i]);
        }
        assertThat(region.keySet().size()).isEqualTo(NB1_NUM_ENTRIES);
      }
    });

    // attachDebugger(vm0, "vm0");
    // attachDebugger(vm2, "vm2");

    // start asynchronous process that does updates to the data
    AsyncInvocation async =
        vm0.invokeAsync(new CacheSerializableRunnable("Do Nonblocking Operations") {
          @Override
          public void run2() throws CacheException {
            Wait.pause(200); // give the gii a chance to start
            Region<Object, Object> region = getRootRegion().getSubregion(name);

            // wait for profile of getInitialImage cache to show up
            final org.apache.geode.internal.cache.CacheDistributionAdvisor adv =
                ((org.apache.geode.internal.cache.DistributedRegion) region)
                    .getCacheDistributionAdvisor();
            // int numProfiles;
            final int expectedProfiles = 1;
            await("profile count never became exactly " + expectedProfiles)
                .until(() -> adv.adviseReplicates().size(), equalTo(expectedProfiles));

            // since we want to force a GII while updates are flying, make sure
            // the other VM gets its CreateRegionResponse and starts its GII
            // before falling into the update loop

            // operate on every odd entry with different value, alternating between
            // updates, invalidates, and destroys. These operations are likely
            // to be nonblocking if a sufficient number of updates get through
            // before the get initial image is complete.
            for (int i = 1; i < 301; i += 2) {
              // getLogWriter().info("doing nonblocking op #"+i);
              Object key = i;
              switch (i % 6) {
                case 1: // UPDATE
                  // use the current timestamp so we know when it happened
                  // we could have used last modification timestamps, but
                  // this works without enabling statistics
                  Object value = System.currentTimeMillis();
                  region.put(key, value);
                  // no longer safe since get is not allowed to member doing GII
                  // if (getRegionAttributes().getScope().isDistributedAck()) {
                  // // do a nonblocking netSearch
                  // region.localInvalidate(key);
                  // assertIndexDetailsEquals(value, region.get(key));
                  // }
                  break;
                case 3: // INVALIDATE
                  region.invalidate(key);
                  if (region.getAttributes().getScope().isDistributedAck()) {
                    // do a nonblocking netSearch
                    value = region.get(key);
                    assertThat(value).describedAs(
                        "Expected null value for key: " + i + " but got " + value).isNull();
                  }
                  break;
                case 5: // DESTROY
                  region.destroy(key);
                  if (region.getAttributes().getScope().isDistributedAck()) {
                    // do a nonblocking netSearch
                    assertThat(region.get(key)).isNull();
                  }
                  break;
                default:
                  fail("unexpected modulus result: " + i);
                  break;
              }
            }

            // at magical number 301, do a region destruction
            // getLogWriter().info("doing destroyRegion");
            region.destroyRegion();
            // getLogWriter().info("finished destroyRegion");
            // now do a put and our DACK root region which will not complete
            // until processed on otherside which means everything done before this
            // point has been processed
            {
              Region<String, String> rr = getRootRegion();
              if (rr != null) {
                rr.put("DONE", "FLUSH_OPS");
              }
            }
          }
        });

    IgnoredException ex = IgnoredException.addIgnoredException("RegionDestroyedException");
    try {
      // in the meantime, do the get initial image in vm2
      AsyncInvocation asyncGII =
          vm2.invokeAsync(new CacheSerializableRunnable("Create Mirrored Region") {
            @Override
            public void run2() throws CacheException {
              if (!getRegionAttributes().getScope().isGlobal()) {
                org.apache.geode.internal.cache.InitialImageOperation.slowImageProcessing = 200;
              }

              beginCacheXml();
              { // root region must be DACK because its used to sync up async subregions
                AttributesFactory<?, ?> factory = new AttributesFactory<>();
                factory.setScope(Scope.DISTRIBUTED_ACK);
                factory.setDataPolicy(DataPolicy.NORMAL);
                factory.setSubscriptionAttributes(new SubscriptionAttributes(InterestPolicy.ALL));
                createRootRegion(factory.create());
              }
              {
                RegionAttributes<?, ?> ra = getRegionAttributes();
                AttributesFactory<?, ?> factory = new AttributesFactory<>(ra);
                if (ra.getDataPolicy().withPersistence()) {
                  factory.setDataPolicy(DataPolicy.PERSISTENT_REPLICATE);
                } else {
                  factory.setDataPolicy(DataPolicy.REPLICATE);
                }
                createRegion(name, factory.create());
              }
              finishCacheXml(name);
              // reset slow
              org.apache.geode.internal.cache.InitialImageOperation.slowImageProcessing = 0;
              // if global scope, the region doesn't get destroyed until after region creation
              try {
                Thread.sleep(3000);
              } catch (InterruptedException ie) {
                fail("interrupted");
              }
              assertThat(getRootRegion().getSubregion(name) == null
                  || getRegionAttributes().getScope().isGlobal()).isTrue();
            }
          });
      if (getRegionAttributes().getScope().isGlobal()) {
        // wait for nonblocking operations to complete
        ThreadUtils.join(async, 30 * 1000);
        if (async.exceptionOccurred()) {
          fail("async invocation failed", async.getException());
        }

        vm2.invoke(new SerializableRunnable("Set fast image processing") {
          @Override
          public void run() {
            org.apache.geode.internal.cache.InitialImageOperation.slowImageProcessing = 0;
          }
        });
        logger.info("after async nonblocking ops complete");
      }

      // wait for GII to complete
      // getLogWriter().info("starting wait for GetInitialImage Completion");
      ThreadUtils.join(asyncGII, 30 * 1000);
      logger.info("Complete GetInitialImage at: " + System.currentTimeMillis());
      if (getRegionAttributes().getScope().isGlobal()) {
        // wait for nonblocking operations to complete
        ThreadUtils.join(async, 30 * 1000);
      }
      if (async.exceptionOccurred()) {
        fail("async failed", async.getException());
      }
      if (asyncGII.exceptionOccurred()) {
        fail("asyncGII failed", asyncGII.getException());
      }
    } finally {
      ex.remove();
    }
  }

  /**
   * Tests what happens when one VM attempts to read an object for which it does not have a
   * registered <code>DataSerializer</code>.
   *
   * @since GemFire 3.5
   */
  @Test
  public void testNoDataSerializer() {
    assertThat(getRegionAttributes().getScope().isDistributed()).isTrue();

    final String name = this.getUniqueName();

    SerializableRunnable create = new CacheSerializableRunnable("Create Region") {
      @Override
      public void run2() throws CacheException {
        createRegion(name);
      }
    };

    VM vm0 = VM.getVM(0);
    VM vm1 = VM.getVM(1);
    VM vm2 = VM.getVM(2);

    logger.info(name + ": before creates");
    vm0.invoke(create);
    vm1.invoke(create);
    logger.info(name + ": after creates");

    final Object key = "KEY";
    final Object key2 = "KEY2";
    final int intValue = 3452;
    final long longValue = 213421;
    // final boolean[] wasInvoked = new boolean[1];

    vm2.invoke(new SerializableRunnable("Disconnect from DS") {
      @Override
      public void run() {
        disconnectFromDS();
      }
    });
    logger.info(name + ": after vm2 disconnect");

    try {
      vm0.invoke(new CacheSerializableRunnable("Put int") {
        @Override
        public void run2() throws CacheException {
          Class c = IntWrapper.IntWrapperSerializer.class;
          IntWrapper.IntWrapperSerializer serializer =
              (IntWrapper.IntWrapperSerializer) DataSerializer.register(c);
          logger.info("Registered serializer id:" + serializer.getId() + " class:" + c.getName());

          Region<Object, Object> region = getRootRegion().getSubregion(name);
          region.put(key, new IntWrapper(intValue));

          flushIfNecessary(region);
          assertThat(serializer.wasInvoked).isTrue();
        }
      });
      logger.info(name + ": after vm0 put");

      SerializableRunnable get = new CacheSerializableRunnable("Get int") {
        @Override
        public void run2() throws CacheException {
          Region<Object, Object> region = getRootRegion().getSubregion(name);
          // wait a while for the serializer to be registered
          // A race condition exists in the product in which
          // this thread can be stuck waiting in getSerializer
          // for 60 seconds. So it only calls getSerializer once
          // causing it to fail intermittently (see GEODE-376).
          // To workaround this the test wets WAIT_MS to 1 ms.
          // So the getSerializer will only block for 1 ms.
          // This allows the WaitCriterion to make multiple calls
          // of getSerializer and the subsequent calls will find
          // the DataSerializer.
          final int savVal = InternalDataSerializer.GetMarker.WAIT_MS;
          InternalDataSerializer.GetMarker.WAIT_MS = 1;
          try {
            await("DataSerializer with id 120 was never registered")
                .until(() -> InternalDataSerializer.getSerializer((byte) 120) != null);
          } finally {
            InternalDataSerializer.GetMarker.WAIT_MS = savVal;
          }
          IntWrapper value = (IntWrapper) region.get(key);
          assertThat(InternalDataSerializer.getSerializer((byte) 120)).isNotNull();
          assertThat(value).isNotNull();
          assertThat(value.intValue).isEqualTo(intValue);
        }
      };
      vm1.invoke(get);
      logger.info(name + ": after vm1 get");

      // Make sure that VMs that connect after registration can get the
      // serializer
      vm2.invoke(new SerializableRunnable("Connect to DS") {
        @Override
        public void run() {
          // Register a DataSerializer before connecting to system
          Class c = LongWrapper.LongWrapperSerializer.class;
          DataSerializer.register(c);

          getSystem();
        }
      });
      vm2.invoke(create);
      logger.info(name + ": after vm2 create");
      vm2.invoke(new CacheSerializableRunnable("Put long") {
        @Override
        public void run2() throws CacheException {
          Region<Object, Object> region = getRootRegion().getSubregion(name);
          region.put(key2, new LongWrapper(longValue));

          flushIfNecessary(region);

          LongWrapper.LongWrapperSerializer serializer =
              (LongWrapper.LongWrapperSerializer) InternalDataSerializer.getSerializer((byte) 121);
          assertThat(serializer.wasInvoked).isTrue();
        }
      });
      logger.info(name + ": after vm2 put");
      vm2.invoke(get);
      logger.info(name + ": after vm2 get");

      SerializableRunnable get2 = new CacheSerializableRunnable("Get long") {
        @Override
        public void run2() throws CacheException {
          Region<Object, Object> region = getRootRegion().getSubregion(name);
          LongWrapper value = (LongWrapper) region.get(key2);
          assertThat(InternalDataSerializer.getSerializer((byte) 121)).isNotNull();
          assertThat(value).isNotNull();
          assertThat(value.longValue).isEqualTo(longValue);
        }
      };
      vm0.invoke(get2);
      logger.info(name + ": after vm0 get2");
      vm1.invoke(get2);
      logger.info(name + ": after vm1 get2");

      // wait a little while for other netsearch requests to return
      // before unregistering the serializers that will be needed to process these
      // responses.
    } finally {
      Wait.pause(1500);
      unregisterAllSerializers();
      logger.info(name + ": after unregister");
    }
  }

  /**
   * Tests what happens when one VM attempts to read an object for which it does not have a
   * registered <code>Instantiator</code>.
   *
   * @since GemFire 3.5
   */
  @Test
  public void testNoInstantiator() {
    assertThat(getRegionAttributes().getScope().isDistributed()).isTrue();

    final String name = this.getUniqueName();

    SerializableRunnable create = new CacheSerializableRunnable("Create Region") {
      @Override
      public void run2() throws CacheException {
        createRegion(name);
      }
    };

    VM vm0 = VM.getVM(0);
    VM vm1 = VM.getVM(1);
    VM vm2 = VM.getVM(2);

    vm0.invoke(create);
    vm1.invoke(create);

    final Object key = "KEY";
    final Object key2 = "KEY2";
    final int intValue = 7201;
    final long longValue = 123612;
    // final boolean[] wasInvoked = new boolean[1];

    vm2.invoke(new SerializableRunnable("Disconnect from DS") {
      @Override
      public void run() {
        disconnectFromDS();
      }
    });

    vm0.invoke(new CacheSerializableRunnable("Put int") {
      @Override
      public void run2() throws CacheException {
        Instantiator.register(new DSIntWrapper.DSIntWrapperInstantiator());

        Region<Object, Object> region = getRootRegion().getSubregion(name);
        region.put(key, new DSIntWrapper(intValue));

        flushIfNecessary(region);
      }
    });

    SerializableRunnable get = new CacheSerializableRunnable("Get int") {
      @Override
      public void run2() throws CacheException {
        Region<Object, Object> region = getRootRegion().getSubregion(name);
        DSIntWrapper.DSIntWrapperInstantiator inst = new DSIntWrapper.DSIntWrapperInstantiator();
        assertThat(InternalInstantiator.getInstantiator(inst.getId())).isNotNull();
        DSIntWrapper value = (DSIntWrapper) region.get(key);
        assertThat(value).isNotNull();
        assertThat(value.intValue).isEqualTo(intValue);
      }
    };
    try {
      vm1.invoke(get);

      // Make sure that VMs that connect after registration can get the
      // serializer
      vm2.invoke(new SerializableRunnable("Connect to DS") {
        @Override
        public void run() {
          // Register a Instantiator before connecting to system
          Instantiator.register(new DSLongWrapper.DSLongWrapperInstantiator());

          getSystem();
        }
      });
      vm2.invoke(create);
      vm2.invoke(new CacheSerializableRunnable("Put long") {
        @Override
        public void run2() throws CacheException {
          Region<Object, Object> region = getRootRegion().getSubregion(name);
          region.put(key2, new DSLongWrapper(longValue));

          flushIfNecessary(region);
        }
      });
      vm2.invoke(get);

      SerializableRunnable get2 = new CacheSerializableRunnable("Get long") {
        @Override
        public void run2() throws CacheException {
          Region<Object, Object> region = getRootRegion().getSubregion(name);
          DSLongWrapper.DSLongWrapperInstantiator inst =
              new DSLongWrapper.DSLongWrapperInstantiator();
          assertThat(InternalInstantiator.getInstantiator(inst.getId())).isNotNull();
          LongWrapper value = (LongWrapper) region.get(key2);
          assertThat(value).isNotNull();
          assertThat(value.longValue).isEqualTo(longValue);

          inst = (DSLongWrapper.DSLongWrapperInstantiator) InternalInstantiator
              .getInstantiator(inst.getId());
          assertThat(inst).isNotNull();
          assertThat(inst.wasInvoked).isTrue();
        }
      };
      vm0.invoke(get2);
      vm1.invoke(get2);

    } finally {
      // wait a little while for other netsearch requests to return
      // before unregistering the serializers that will be needed to process these
      // responses.
      Wait.pause(1500);
      unregisterAllSerializers();
    }
  }

  /**
   * Unregisters all of the <code>DataSerializer</code>s and <code>Instantiators</code> in all of
   * the VMs in the distributed system.
   */
  private static void unregisterAllSerializers() {
    DistributedTestUtils.unregisterAllDataSerializersFromAllVms();
  }

  /**
   * A class used when testing <code>DataSerializable</code> and distribution.
   */
  static class IntWrapper {
    int intValue;

    IntWrapper(int intValue) {
      this.intValue = intValue;
    }

    @Override
    public boolean equals(Object o) {
      if (o instanceof IntWrapper) {
        return ((IntWrapper) o).intValue == this.intValue;

      } else {
        return false;
      }
    }

    static class IntWrapperSerializer extends DataSerializer {
      boolean wasInvoked = false;

      @Override
      public int getId() {
        return 120;
      }

      @Override
      public Class[] getSupportedClasses() {
        return new Class[] {IntWrapper.class};
      }

      @Override
      public boolean toData(Object o, DataOutput out) throws IOException {
        if (o instanceof IntWrapper) {
          this.wasInvoked = true;
          IntWrapper iw = (IntWrapper) o;
          out.writeInt(iw.intValue);
          return true;

        } else {
          return false;
        }
      }

      @Override
      public Object fromData(DataInput in) throws IOException {

        return new IntWrapper(in.readInt());
      }
    }
  }

  /**
   * An <code>IntWrapper</code> that is <code>DataSerializable</code>.
   */
  static class DSIntWrapper extends IntWrapper implements DataSerializable {

    DSIntWrapper(int intValue) {
      super(intValue);
    }

    DSIntWrapper() {
      super(0);
    }

    @Override
    public void toData(DataOutput out) throws IOException {
      out.writeInt(intValue);
    }

    @Override
    public void fromData(DataInput in) throws IOException {
      this.intValue = in.readInt();
    }

    static class DSIntWrapperInstantiator extends Instantiator {
      DSIntWrapperInstantiator() {
        this(DSIntWrapper.class, (byte) 76);
      }

      DSIntWrapperInstantiator(Class<? extends DSIntWrapper> c, byte id) {
        super(c, id);
      }

      @Override
      public DataSerializable newInstance() {
        return new DSIntWrapper();
      }
    }
  }

  /**
   * Another class used when testing <code>DataSerializable</code> and distribution.
   */
  static class LongWrapper {
    long longValue;

    LongWrapper(long longValue) {
      this.longValue = longValue;
    }

    @Override
    public boolean equals(Object o) {
      if (o instanceof LongWrapper) {
        return ((LongWrapper) o).longValue == this.longValue;

      } else {
        return false;
      }
    }

    static class LongWrapperSerializer extends DataSerializer {
      boolean wasInvoked = false;

      @Override
      public int getId() {
        return 121;
      }

      @Override
      public Class[] getSupportedClasses() {
        return new Class[] {LongWrapper.class};
      }

      @Override
      public boolean toData(Object o, DataOutput out) throws IOException {
        if (o instanceof LongWrapper) {
          this.wasInvoked = true;
          LongWrapper iw = (LongWrapper) o;
          out.writeLong(iw.longValue);
          return true;

        } else {
          return false;
        }
      }

      @Override
      public Object fromData(DataInput in) throws IOException {

        return new LongWrapper(in.readLong());
      }
    }
  }

  /**
   * An <code>LongWrapper</code> that is <code>DataSerializable</code>.
   */
  static class DSLongWrapper extends LongWrapper implements DataSerializable {

    DSLongWrapper(long longValue) {
      super(longValue);
    }

    DSLongWrapper() {
      super(0L);
    }

    @Override
    public void toData(DataOutput out) throws IOException {
      out.writeLong(longValue);
    }

    @Override
    public void fromData(DataInput in) throws IOException {
      this.longValue = in.readLong();
    }

    static class DSLongWrapperInstantiator extends Instantiator {
      boolean wasInvoked = false;

      DSLongWrapperInstantiator(Class<? extends DSLongWrapper> c, byte id) {
        super(c, id);
      }

      DSLongWrapperInstantiator() {
        this(DSLongWrapper.class, (byte) 99);
      }

      @Override
      public DataSerializable newInstance() {
        this.wasInvoked = true;
        return new DSLongWrapper();
      }
    }
  }

  private static class MyTransactionListener implements TransactionListener {
    private volatile TransactionId expectedTxId;
    private volatile TransactionEvent lastEvent;
    private volatile int afterCommitCount;
    private volatile int afterFailedCommitCount;
    private volatile int afterRollbackCount;
    private volatile int closeCount;

    @Override
    public synchronized void afterCommit(TransactionEvent event) {
      this.lastEvent = event;
      this.afterCommitCount++;
    }

    @Override
    public synchronized void afterFailedCommit(TransactionEvent event) {
      this.lastEvent = event;
      this.afterFailedCommitCount++;
    }

    @Override
    public synchronized void afterRollback(TransactionEvent event) {
      this.lastEvent = event;
      this.afterRollbackCount++;
    }

    @Override
    public synchronized void close() {
      this.closeCount++;
    }

    synchronized void checkAfterCommitCount(int expected) {
      assertThat(this.afterCommitCount).isEqualTo(expected);
    }

    synchronized void assertCounts(int commitCount, int failedCommitCount, int rollbackCount,
        int closeCount1) {
      assertSoftly((softly) -> {
        softly.assertThat(afterCommitCount).describedAs("After Commit Count")
            .isEqualTo(commitCount);
        softly.assertThat(afterFailedCommitCount).describedAs("After Failed Commit Count")
            .isEqualTo(failedCommitCount);
        softly.assertThat(afterRollbackCount).describedAs("After Rollback Count")
            .isEqualTo(rollbackCount);
        softly.assertThat(closeCount).describedAs("Close Count")
            .isEqualTo(closeCount1);
      });
    }
  }

  private static class CountingDistCacheListener<K, V> extends CacheListenerAdapter<K, V> {
    private int aCreateCalls, aUpdateCalls, aInvalidateCalls, aDestroyCalls, regionOps;
    private EntryEvent<K, V> lastEvent;

    @Override
    public void close() {}

    @Override
    public void afterCreate(EntryEvent<K, V> e) {
      if (e.isOriginRemote()) {
        synchronized (this) {
          ++this.aCreateCalls;
          this.lastEvent = e;
        }
      }
    }

    @Override
    public void afterUpdate(EntryEvent<K, V> e) {
      if (e.isOriginRemote()) {
        synchronized (this) {
          ++this.aUpdateCalls;
          this.lastEvent = e;
        }
      }
    }

    @Override
    public void afterInvalidate(EntryEvent<K, V> e) {
      if (e.isOriginRemote()) {
        synchronized (this) {
          ++this.aInvalidateCalls;
          this.lastEvent = e;
        }
      }
    }

    @Override
    public void afterDestroy(EntryEvent<K, V> e) {
      if (e.isOriginRemote()) {
        synchronized (this) {
          ++this.aDestroyCalls;
          this.lastEvent = e;
        }
      }
    }

    @Override
    public synchronized void afterRegionInvalidate(RegionEvent<K, V> e) {
      ++this.regionOps;
    }

    @Override
    public synchronized void afterRegionDestroy(RegionEvent<K, V> e) {
      ++this.regionOps;
    }

    synchronized void assertCount(int expectedCreate, int expectedUpdate,
        int expectedInvalidate, int expectedDestroy) {
      assertThat(this.aCreateCalls).isEqualTo(expectedCreate);
      assertThat(this.aUpdateCalls).isEqualTo(expectedUpdate);
      assertThat(this.aInvalidateCalls).isEqualTo(expectedInvalidate);
      assertThat(this.aDestroyCalls).isEqualTo(expectedDestroy);
      assertThat(this.regionOps).isEqualTo(0);
    }

    synchronized EntryEvent<K, V> getEntryEvent() {
      return this.lastEvent;
    }

    synchronized void setEntryEvent(EntryEvent<K, V> event) {
      this.lastEvent = event;
    }
  }

  private void assertCacheCallbackEvents(String regionName, TransactionId txId, Object key,
      Object oldValue, Object newValue) {
    Region<Object, Object> re = getCache().getRegion("root").getSubregion(regionName);
    MyTransactionListener tl =
        firstTransactionListenerFrom(getCache().getCacheTransactionManager());
    tl.expectedTxId = txId;
    assertThat(re).describedAs("Cannot assert TX Callout Events with a null Region: " + regionName)
        .isNotNull();
    final CountingDistCacheListener<Object, Object> cdcl =
        (CountingDistCacheListener<Object, Object>) re.getAttributes().getCacheListeners()[0];

    await("retry event = null where it should not be")
        .until(() -> cdcl.getEntryEvent() != null);

    EntryEvent<Object, Object> listenEvent = cdcl.getEntryEvent();
    assertThat(listenEvent).describedAs(
        "Cannot assert TX CacheListener Events with a null Entry Event").isNotNull();
    assertThat(listenEvent.getRegion()).isEqualTo(re);
    assertThat(listenEvent.getTransactionId()).isEqualTo(txId);
    assertThat(listenEvent.getKey()).isEqualTo(key);
    assertThat(listenEvent.getOldValue()).isEqualTo(oldValue);
    assertThat(listenEvent.getNewValue()).isEqualTo(newValue);
    assertThat(listenEvent.getCallbackArgument()).isNull();
    assertThat(listenEvent.isCallbackArgumentAvailable()).isTrue();
    assertThat(listenEvent.getOperation().isLoad()).isFalse();
    assertThat(listenEvent.getOperation().isNetLoad()).isFalse();
    assertThat(listenEvent.getOperation().isNetSearch()).isFalse();
    assertThat(listenEvent.getOperation().isLocalLoad()).isFalse();
    assertThat(listenEvent.getOperation().isDistributed()).isTrue();
    assertThat(listenEvent.getOperation().isExpiration()).isFalse();
    assertThat(listenEvent.isOriginRemote()).isTrue();
    cdcl.setEntryEvent(null);
  }

  /**
   * Tests that an entry update is propagated to other caches that have that same entry defined.
   */
  @Test
  public void testTXSimpleOps() {
    assumeThat(supportsTransactions()).isTrue();

    assertThat(getRegionAttributes().getScope().isDistributed()).isTrue();
    CacheTransactionManager txMgr = this.getCache().getCacheTransactionManager();

    if (getRegionAttributes().getScope().isGlobal()
        || getRegionAttributes().getDataPolicy().withPersistence()) {
      // just make sure transactions are not allowed on global or shared regions
      Region<String, String> rgn = createRegion(getUniqueName());
      txMgr.begin();
      assertThatThrownBy(() -> rgn.put("testTXSimpleOpsKey1", "val"))
          .isInstanceOf(UnsupportedOperationException.class);

      txMgr.rollback();
      rgn.localDestroyRegion();
      return;
    }

    final String rgnName = getUniqueName();

    SerializableRunnable create = new SerializableRunnable("testTXSimpleOps: Create Region") {
      @Override
      public void run() {
        CacheTransactionManager txMgr2 = getCache().getCacheTransactionManager();
        MyTransactionListener tl = new MyTransactionListener();
        setTxListener(txMgr2, tl);
        assertThat(tl.lastEvent).isNull();
        assertThat(tl.afterCommitCount).isEqualTo(0);
        assertThat(tl.afterFailedCommitCount).isEqualTo(0);
        assertThat(tl.afterRollbackCount).isEqualTo(0);
        assertThat(tl.closeCount).isEqualTo(0);
        try {
          Region<Object, Object> rgn = createRegion(rgnName);
          CountingDistCacheListener<Object, Object> cacheListener =
              new CountingDistCacheListener<>();
          rgn.getAttributesMutator().addCacheListener(cacheListener);
          cacheListener.assertCount(0, 0, 0, 0);
          getSystem().getLogWriter().info("testTXSimpleOps: Created region");
        } catch (CacheException e) {
          fail("While creating region", e);
        }
      }
    };

    SerializableRunnable newKey =
        new SerializableRunnable("testTXSimpleOps: Create Region & Create Key") {
          @Override
          public void run() {
            try {
              Region<?, ?> root = getRootRegion();
              Region<Object, Object> rgn = root.getSubregion(rgnName);
              rgn.create("key", null);
              CountingDistCacheListener cacheListener =
                  (CountingDistCacheListener) rgn.getAttributes().getCacheListeners()[0];
              cacheListener.assertCount(0, 0, 0, 0);
              getSystem().getLogWriter().info("testTXSimpleOps: Created Key");
            } catch (CacheException e) {
              fail("While creating region", e);
            }
          }
        };

    VM vm = VM.getVM(0);
    vm.invoke(create);
    vm.invoke(newKey);
    int vmCount = VM.getVMCount();
    for (int i = 1; i < vmCount; i++) {
      vm = VM.getVM(i);
      vm.invoke(create);
      if (!getRegionAttributes().getDataPolicy().withReplication()
          && !getRegionAttributes().getDataPolicy().withPreloaded()) {
        vm.invoke(newKey);
      }
    }
    // GemFireVersion.waitForJavaDebugger(getLogWriter(), "CTRLR WAITING AFTER CREATE");

    try {
      Region<String, String> rgn = createRegion(rgnName);
      DMStats dmStats = getSystem().getDistributionManager().getStats();
      long cmtMsgs = dmStats.getSentCommitMessages();
      long commitWaits = dmStats.getCommitWaits();

      {
        txMgr.begin();
        rgn.put("key", "value");
        final TransactionId txId = txMgr.getTransactionId();
        txMgr.commit();
        assertThat(dmStats.getSentCommitMessages()).isEqualTo(cmtMsgs + 1);
        if (rgn.getAttributes().getScope().isAck()) {
          assertThat(dmStats.getCommitWaits()).isEqualTo(commitWaits + 1);
        } else {
          assertThat(dmStats.getCommitWaits()).isEqualTo(commitWaits);
        }
        getSystem().getLogWriter().info("testTXSimpleOps: Create/Put Value");
        invokeInEveryVM(new SerializableRunnable() {
          @Override
          public void run() {
            assertCacheCallbackEvents(rgnName, txId, "key", null, "value");
          }
        });
        invokeInEveryVM(repeatingIfNecessary(
            new CacheSerializableRunnable("testTXSimpleOps: Verify Received Value") {
              @Override
              public void run2() {
                Region<String, String> rgn1 = getRootRegion().getSubregion(rgnName);
                assertThat(rgn1.getEntry("key")).describedAs("Could not find entry for 'key'")
                    .isNotNull();
                assertThat(rgn1.getEntry("key").getValue()).isEqualTo("value");
                CacheTransactionManager txMgr2 = getCache().getCacheTransactionManager();
                MyTransactionListener tl =
                    firstTransactionListenerFrom(txMgr2);
                tl.checkAfterCommitCount(1);
                assertThat(tl.afterFailedCommitCount).isEqualTo(0);
                assertThat(tl.afterRollbackCount).isEqualTo(0);
                assertThat(tl.closeCount).isEqualTo(0);
                assertThat(tl.lastEvent.getCache()).isEqualTo(rgn1.getRegionService());
                {
                  Collection<EntryEvent<?, ?>> events;
                  RegionAttributes<String, String> attr = getRegionAttributes();
                  if (!attr.getDataPolicy().withReplication()
                      || attr.getConcurrencyChecksEnabled()) {
                    events = TxEventTestUtil.getPutEvents(tl.lastEvent.getEvents());
                  } else {
                    events = TxEventTestUtil.getCreateEvents(tl.lastEvent.getEvents());
                  }
                  assertThat(events.size()).isEqualTo(1);
                  EntryEvent ev = events.iterator().next();
                  assertThat(ev.getTransactionId()).isEqualTo(tl.expectedTxId);
                  assertThat(rgn1).isSameAs(ev.getRegion());
                  assertThat(ev.getKey()).isEqualTo("key");
                  assertThat(ev.getNewValue()).isEqualTo("value");
                  assertThat(ev.getOldValue()).isNull();
                  assertThat(ev.getOperation().isLocalLoad()).isFalse();
                  assertThat(ev.getOperation().isNetLoad()).isFalse();
                  assertThat(ev.getOperation().isLoad()).isFalse();
                  assertThat(ev.getOperation().isNetSearch()).isFalse();
                  assertThat(ev.getOperation().isExpiration()).isFalse();
                  assertThat(ev.getCallbackArgument()).isNull();
                  assertThat(ev.isCallbackArgumentAvailable()).isTrue();
                  assertThat(ev.isOriginRemote()).isTrue();
                  assertThat(ev.getOperation().isDistributed()).isTrue();
                }
                CountingDistCacheListener<String, String> cdcL =
                    (CountingDistCacheListener<String, String>) rgn1.getAttributes()
                        .getCacheListeners()[0];
                cdcL.assertCount(0, 1, 0, 0);
              }
            }));
      }

      {
        txMgr.begin();
        rgn.put("key", "value2");
        final TransactionId txId = txMgr.getTransactionId();
        txMgr.commit();
        getSystem().getLogWriter().info("testTXSimpleOps: Put(update) Value2");
        invokeInEveryVM(new SerializableRunnable() {
          @Override
          public void run() {
            assertCacheCallbackEvents(rgnName, txId, "key", "value", "value2");
          }
        });
        invokeInEveryVM(repeatingIfNecessary(
            new CacheSerializableRunnable("testTXSimpleOps: Verify Received Value") {
              @Override
              public void run2() {
                Region<String, String> rgn1 = getRootRegion().getSubregion(rgnName);
                assertThat(rgn1.getEntry("key")).describedAs("Could not find entry for 'key'")
                    .isNotNull();
                assertThat(rgn1.getEntry("key").getValue()).isEqualTo("value2");
                CacheTransactionManager txMgr2 = getCache().getCacheTransactionManager();
                MyTransactionListener tl = firstTransactionListenerFrom(txMgr2);
                tl.checkAfterCommitCount(2);
                assertThat(tl.lastEvent.getCache()).isEqualTo(rgn1.getRegionService());
                {
                  Collection<EntryEvent<?, ?>> events =
                      TxEventTestUtil.getPutEvents(tl.lastEvent.getEvents());
                  assertThat(events.size()).isEqualTo(1);
                  EntryEvent<?, ?> ev = events.iterator().next();
                  assertThat(ev.getTransactionId()).isEqualTo(tl.expectedTxId);
                  assertThat(rgn1).isSameAs(ev.getRegion());
                  assertThat(ev.getKey()).isEqualTo("key");
                  assertThat(ev.getNewValue()).isEqualTo("value2");
                  assertThat(ev.getOldValue()).isEqualTo("value");
                  assertThat(ev.getOperation().isLocalLoad()).isFalse();
                  assertThat(ev.getOperation().isNetLoad()).isFalse();
                  assertThat(ev.getOperation().isLoad()).isFalse();
                  assertThat(ev.getOperation().isNetSearch()).isFalse();
                  assertThat(ev.getOperation().isExpiration()).isFalse();
                  assertThat(ev.getCallbackArgument()).isNull();
                  assertThat(ev.isCallbackArgumentAvailable()).isTrue();
                  assertThat(ev.isOriginRemote()).isTrue();
                  assertThat(ev.getOperation().isDistributed()).isTrue();
                }
                CountingDistCacheListener cdcL =
                    (CountingDistCacheListener) rgn1.getAttributes().getCacheListeners()[0];
                cdcL.assertCount(0, 2, 0, 0);
              }
            }));
      }

      {
        txMgr.begin();
        rgn.invalidate("key");
        final TransactionId txId = txMgr.getTransactionId();
        txMgr.commit();
        getSystem().getLogWriter().info("testTXSimpleOps: invalidate key");
        // validate each of the CacheListeners EntryEvents
        invokeInEveryVM(new SerializableRunnable() {
          @Override
          public void run() {
            assertCacheCallbackEvents(rgnName, txId, "key", "value2", null);
          }
        });
        invokeInEveryVM(repeatingIfNecessary(
            new CacheSerializableRunnable("testTXSimpleOps: Verify Received Value") {
              @Override
              public void run2() {
                Region<String, String> rgn1 = getRootRegion().getSubregion(rgnName);
                assertThat(rgn1.getEntry("key")).describedAs("entry for 'key'")
                    .isNotNull();
                assertThat(rgn1.containsKey("key")).isTrue();
                assertThat(rgn1.containsValueForKey("key")).isFalse();
                CacheTransactionManager txMgr2 = getCache().getCacheTransactionManager();
                MyTransactionListener tl =
                    firstTransactionListenerFrom(txMgr2);
                tl.checkAfterCommitCount(3);
                assertThat(tl.lastEvent.getCache()).isEqualTo(rgn1.getRegionService());
                {
                  List<EntryEvent<?, ?>> events =
                      TxEventTestUtil.getInvalidateEvents(tl.lastEvent.getEvents());
                  assertThat(events.size()).isEqualTo(1);
                  EntryEvent<?, ?> ev = events.get(0);
                  assertThat(ev.getTransactionId()).isEqualTo(tl.expectedTxId);
                  assertThat(rgn1).isSameAs(ev.getRegion());
                  assertThat(ev.getKey()).isEqualTo("key");
                  assertThat(ev.getNewValue()).isNull();
                  assertThat(ev.getOldValue()).isEqualTo("value2");
                  assertThat(ev.getOperation().isLocalLoad()).isFalse();
                  assertThat(ev.getOperation().isNetLoad()).isFalse();
                  assertThat(ev.getOperation().isLoad()).isFalse();
                  assertThat(ev.getOperation().isNetSearch()).isFalse();
                  assertThat(ev.getOperation().isExpiration()).isFalse();
                  assertThat(ev.getCallbackArgument()).isNull();
                  assertThat(ev.isCallbackArgumentAvailable()).isTrue();
                  assertThat(ev.isOriginRemote()).isTrue();
                  assertThat(ev.getOperation().isDistributed()).isTrue();
                }
                CountingDistCacheListener cdcL =
                    (CountingDistCacheListener) rgn1.getAttributes().getCacheListeners()[0];
                cdcL.assertCount(0, 2, 1, 0);
              }
            }));
      }

      {
        txMgr.begin();
        rgn.destroy("key");
        TransactionId txId = txMgr.getTransactionId();
        txMgr.commit();
        getSystem().getLogWriter().info("testTXSimpleOps: destroy key");
        // validate each of the CacheListeners EntryEvents
        invokeInEveryVM(new SerializableRunnable() {
          @Override
          public void run() {
            assertCacheCallbackEvents(rgnName, txId, "key", null, null);
          }
        });
        invokeInEveryVM(repeatingIfNecessary(
            new CacheSerializableRunnable("testTXSimpleOps: Verify Received Value") {
              @Override
              public void run2() {
                Region<String, String> rgn1 = getRootRegion().getSubregion(rgnName);
                assertThat(rgn1.containsKey("key")).isFalse();
                CacheTransactionManager txMgr2 = getCache().getCacheTransactionManager();
                MyTransactionListener tl = firstTransactionListenerFrom(txMgr2);
                tl.checkAfterCommitCount(4);
                assertThat(tl.lastEvent.getCache()).isEqualTo(rgn1.getRegionService());
                {
                  Collection<EntryEvent<?, ?>> events =
                      TxEventTestUtil.getDestroyEvents(tl.lastEvent.getEvents());
                  assertThat(events.size()).isEqualTo(1);
                  EntryEvent<?, ?> ev = events.iterator().next();
                  assertThat(ev.getTransactionId()).isEqualTo(tl.expectedTxId);
                  assertThat(rgn1).isSameAs(ev.getRegion());
                  assertThat(ev.getKey()).isEqualTo("key");
                  assertThat(ev.getNewValue()).isNull();
                  assertThat(ev.getOldValue()).isNull();
                  assertThat(ev.getOperation().isLocalLoad()).isFalse();
                  assertThat(ev.getOperation().isNetLoad()).isFalse();
                  assertThat(ev.getOperation().isLoad()).isFalse();
                  assertThat(ev.getOperation().isNetSearch()).isFalse();
                  assertThat(ev.getOperation().isExpiration()).isFalse();
                  assertThat(ev.getCallbackArgument()).isNull();
                  assertThat(ev.isCallbackArgumentAvailable()).isTrue();
                  assertThat(ev.isOriginRemote()).isTrue();
                  assertThat(ev.getOperation().isDistributed()).isTrue();
                }
                CountingDistCacheListener cdcL =
                    (CountingDistCacheListener) rgn1.getAttributes().getCacheListeners()[0];
                cdcL.assertCount(0, 2, 1, 1);
              }
            }));
      }
    } catch (Exception e) {
      getCache().close();
      getSystem().getLogWriter().fine("testTXSimpleOps: Caused exception in createRegion");
      throw e;
    }

  }

  /**
   * Indicate whether this region supports transactions
   *
   * @return true if it supports transactions
   */
  protected boolean supportsTransactions() {
    return true;
  }

  /**
   * Tests that the push of a loaded value does not cause a conflict on the side receiving the
   * update
   */
  @Ignore("TODO: this test always hits early out")
  @Test
  public void testTXUpdateLoadNoConflict() {
    assumeThat(supportsTransactions()).isTrue();
    assumeThat(getRegionAttributes().getScope().isGlobal()).isFalse();
    assumeThat(getRegionAttributes().getDataPolicy().withPersistence()).isFalse();

    assertThat(getRegionAttributes().getScope().isDistributed()).isTrue();
    CacheTransactionManager txMgr = this.getCache().getCacheTransactionManager();

    final String rgnName = getUniqueName();

    SerializableRunnable create =
        new SerializableRunnable("testTXUpdateLoadNoConflict: Create Region & Load value") {
          @Override
          public void run() {
            CacheTransactionManager txMgr2 = getCache().getCacheTransactionManager();
            MyTransactionListener tl = new MyTransactionListener();
            setTxListener(txMgr2, tl);
            try {
              Region<String, String> rgn = createRegion(rgnName);
              AttributesMutator<String, String> mutator = rgn.getAttributesMutator();
              mutator.setCacheLoader(new CacheLoader<String, String>() {
                int count = 0;

                @Override
                public String load(LoaderHelper<String, String> helper)
                    throws CacheLoaderException {
                  count++;
                  return "LV " + count;
                }

                @Override
                public void close() {}
              });
              Object value = rgn.get("key");
              assertThat(value).isEqualTo("LV 1");
              getSystem().getLogWriter().info("testTXUpdateLoadNoConflict: loaded Key");
              flushIfNecessary(rgn);
            } catch (CacheException e) {
              fail("While creating region", e);
            }
          }
        };

    VM vm0 = VM.getVM(0);
    // GemFireVersion.waitForJavaDebugger(getLogWriter(), "CTRLR WAITING AFTER CREATE");

    try {
      MyTransactionListener tl = new MyTransactionListener();
      setTxListener(txMgr, tl);
      AttributesFactory<String, String> rgnAtts = new AttributesFactory<>(getRegionAttributes());
      rgnAtts.setDataPolicy(DataPolicy.REPLICATE);
      Region<String, String> rgn = createRegion(rgnName, rgnAtts.create());

      txMgr.begin();
      TransactionId myTXId = txMgr.getTransactionId();

      rgn.create("key", "txValue");

      vm0.invoke(create);

      {
        TXStateProxy tx = ((TXManagerImpl) txMgr).pauseTransaction();
        assertThat(rgn.containsKey("key")).isTrue();
        assertThat(rgn.getEntry("key").getValue()).isEqualTo("LV 1");
        ((TXManagerImpl) txMgr).unpauseTransaction(tx);
      }
      // make sure transactional view is still correct
      assertThat(rgn.getEntry("key").getValue()).isEqualTo("txValue");

      txMgr.commit();
      getSystem().getLogWriter().info("testTXUpdateLoadNoConflict: did commit");
      assertThat(rgn.getEntry("key").getValue()).isEqualTo("txValue");
      {
        Collection<EntryEvent<?, ?>> events =
            TxEventTestUtil.getCreateEvents(tl.lastEvent.getEvents());
        assertThat(events.size()).isEqualTo(1);
        EntryEvent<?, ?> ev = events.iterator().next();
        assertThat(ev.getTransactionId()).isEqualTo(myTXId);
        assertThat(rgn).isSameAs(ev.getRegion());
        assertThat(ev.getKey()).isEqualTo("key");
        assertThat(ev.getNewValue()).isEqualTo("txValue");
        assertThat(ev.getOldValue()).isNull();
        assertThat(ev.getOperation().isLocalLoad()).isFalse();
        assertThat(ev.getOperation().isNetLoad()).isFalse();
        assertThat(ev.getOperation().isLoad()).isFalse();
        assertThat(ev.getOperation().isNetSearch()).isFalse();
        assertThat(ev.getOperation().isExpiration()).isFalse();
        assertThat(ev.getCallbackArgument()).isNull();
        assertThat(ev.isCallbackArgumentAvailable()).isTrue();
        assertThat(ev.isOriginRemote()).isFalse();
        assertThat(ev.getOperation().isDistributed()).isTrue();
      }

      // Now setup recreate the region in the controller with NONE
      // so test can do local destroys.
      rgn.localDestroyRegion();
      rgnAtts.setDataPolicy(DataPolicy.NORMAL);
      rgn = createRegion(rgnName, rgnAtts.create());

      // now see if net loader is working
      Object v2 = rgn.get("key2");
      assertThat(v2).isEqualTo("LV 2");

      // now confirm that netload does not cause a conflict
      txMgr.begin();
      myTXId = txMgr.getTransactionId();

      rgn.create("key3", "txValue3");

      {
        TXStateProxy tx = ((TXManagerImpl) txMgr).pauseTransaction();
        // do a get outside of the transaction to force a net load
        Object v3 = rgn.get("key3");
        assertThat(v3).isEqualTo("LV 3");
        ((TXManagerImpl) txMgr).unpauseTransaction(tx);
      }
      // make sure transactional view is still correct
      assertThat(rgn.getEntry("key3").getValue()).isEqualTo("txValue3");

      txMgr.commit();
      getSystem().getLogWriter().info("testTXUpdateLoadNoConflict: did commit");
      assertThat(rgn.getEntry("key3").getValue()).isEqualTo("txValue3");
      {
        Collection<EntryEvent<?, ?>> events =
            TxEventTestUtil.getCreateEvents(tl.lastEvent.getEvents());
        assertThat(events.size()).isEqualTo(1);
        EntryEvent<?, ?> ev = events.iterator().next();
        assertThat(ev.getTransactionId()).isEqualTo(myTXId);
        assertThat(rgn).isSameAs(ev.getRegion());
        assertThat(ev.getKey()).isEqualTo("key3");
        assertThat(ev.getNewValue()).isEqualTo("txValue3");
        assertThat(ev.getOldValue()).isNull();
        assertThat(ev.getOperation().isLocalLoad()).isFalse();
        assertThat(ev.getOperation().isNetLoad()).isFalse();
        assertThat(ev.getOperation().isLoad()).isFalse();
        assertThat(ev.getOperation().isNetSearch()).isFalse();
        assertThat(ev.getOperation().isExpiration()).isFalse();
        assertThat(ev.getCallbackArgument()).isNull();
        assertThat(ev.isCallbackArgumentAvailable()).isTrue();
        assertThat(ev.isOriginRemote()).isFalse();
        assertThat(ev.getOperation().isDistributed()).isTrue();
      }

      // now see if tx net loader is working

      // now confirm that netload does not cause a conflict
      txMgr.begin();
      Object v4 = rgn.get("key4");
      assertThat(v4).isEqualTo("LV 4");
      assertThat(rgn.get("key4")).isEqualTo("LV 4");
      assertThat(rgn.getEntry("key4").getValue()).isEqualTo("LV 4");
      txMgr.rollback();
      // confirm that netLoad is transactional
      assertThat(rgn.get("key4")).isEqualTo("LV 5");
      assertThat(rgn.getEntry("key4").getValue()).isEqualTo("LV 5");

      // make sure non-tx netsearch works
      assertThat(rgn.get("key")).isEqualTo("txValue");
      assertThat(rgn.getEntry("key").getValue()).isEqualTo("txValue");

      // make sure net-search result does not conflict with commit
      rgn.localInvalidate("key");
      txMgr.begin();
      myTXId = txMgr.getTransactionId();

      rgn.put("key", "new txValue");

      {
        TXStateProxy tx = ((TXManagerImpl) txMgr).pauseTransaction();
        // do a get outside of the transaction to force a netsearch
        assertThat(rgn.get("key")).isEqualTo("txValue");
        assertThat(rgn.getEntry("key").getValue()).isEqualTo("txValue");
        ((TXManagerImpl) txMgr).unpauseTransaction(tx);
      }
      // make sure transactional view is still correct
      assertThat(rgn.getEntry("key").getValue()).isEqualTo("new txValue");

      txMgr.commit();
      flushIfNecessary(rgn); // give other side change to process commit
      getSystem().getLogWriter().info("testTXUpdateLoadNoConflict: did commit");
      assertThat(rgn.getEntry("key").getValue()).isEqualTo("new txValue");
      {
        Collection<EntryEvent<?, ?>> events =
            TxEventTestUtil.getPutEvents(tl.lastEvent.getEvents());
        assertThat(events.size()).isEqualTo(1);
        EntryEvent<?, ?> ev = events.iterator().next();
        assertThat(ev.getTransactionId()).isEqualTo(myTXId);
        assertThat(rgn).isSameAs(ev.getRegion());
        assertThat(ev.getKey()).isEqualTo("key");
        assertThat(ev.getNewValue()).isEqualTo("new txValue");
        assertThat(ev.getOldValue()).isNull();
        assertThat(ev.getOperation().isLocalLoad()).isFalse();
        assertThat(ev.getOperation().isNetLoad()).isFalse();
        assertThat(ev.getOperation().isLoad()).isFalse();
        assertThat(ev.getOperation().isNetSearch()).isFalse();
        assertThat(ev.getOperation().isExpiration()).isFalse();
        assertThat(ev.getCallbackArgument()).isNull();
        assertThat(ev.isCallbackArgumentAvailable()).isTrue();
        assertThat(ev.isOriginRemote()).isFalse();
        assertThat(ev.getOperation().isDistributed()).isTrue();
      }

      // make sure tx local invalidate allows netsearch
      Object localCmtValue = rgn.getEntry("key").getValue();
      txMgr.begin();
      assertThat(rgn.getEntry("key").getValue()).isSameAs(localCmtValue);
      rgn.localInvalidate("key");
      assertThat(rgn.getEntry("key").getValue()).isNull();
      // now make sure a get will do a netsearch and find the value
      // in the other vm instead of the one in local cmt state
      Object txValue = rgn.get("key");
      assertThat(txValue).isNotSameAs(localCmtValue);
      assertThat(rgn.get("key")).isSameAs(txValue);
      assertThat(rgn.getEntry("key").getValue()).isNotSameAs(localCmtValue);
      // make sure we did a search and not a load
      assertThat(rgn.getEntry("key").getValue()).isEqualTo(localCmtValue);
      // now make sure that if we do a tx distributed invalidate
      // that we will do a load and not a search
      rgn.invalidate("key");
      assertThat(rgn.getEntry("key").getValue()).isNull();
      txValue = rgn.get("key");
      assertThat(txValue).isEqualTo("LV 6");
      assertThat(rgn.get("key")).isSameAs(txValue);
      assertThat(rgn.getEntry("key").getValue()).isEqualTo("LV 6");
      // now make sure after rollback that local cmt state has not changed
      txMgr.rollback();
      assertThat(rgn.getEntry("key").getValue()).isSameAs(localCmtValue);
    } catch (Exception e) {
      getCache().close();
      getSystem().getLogWriter()
          .fine("testTXUpdateLoadNoConflict: Caused exception in createRegion");
      throw e;
    }
  }

  @Test
  public void testTXMultiRegion() {
    assumeThat(supportsTransactions()).isTrue();
    assumeThat(getRegionAttributes().getScope().isGlobal()).isFalse();
    assumeThat(getRegionAttributes().getDataPolicy().withPersistence()).isFalse();

    assertThat(getRegionAttributes().getScope().isDistributed()).isTrue();

    CacheTransactionManager txMgr = this.getCache().getCacheTransactionManager();

    final String rgnName1 = getUniqueName() + "MR1";
    final String rgnName2 = getUniqueName() + "MR2";
    final String rgnName3 = getUniqueName() + "MR3";

    SerializableRunnable create1 = new SerializableRunnable("testTXMultiRegion: Create Region") {
      @Override
      public void run() {
        CacheTransactionManager txMgr2 = getCache().getCacheTransactionManager();
        MyTransactionListener tl = new MyTransactionListener();
        setTxListener(txMgr2, tl);
        try {
          createRegion(rgnName1);
          getSystem().getLogWriter().info("testTXMultiRegion: Created region1");
        } catch (CacheException e) {
          fail("While creating region", e);
        }
      }
    };
    SerializableRunnable newKey1 = new SerializableRunnable("testTXMultiRegion: Create Key") {
      @Override
      public void run() {
        try {
          Region<String, ?> rgn = getRootRegion("root").getSubregion(rgnName1);
          rgn.create("key", null);
          getSystem().getLogWriter().info("testTXMultiRegion: Created key");
        } catch (CacheException e) {
          fail("While creating region", e);
        }
      }
    };

    SerializableRunnable create2 = new SerializableRunnable("testTXMultiRegion: Create Region") {
      @Override
      public void run() {
        CacheTransactionManager txMgr2 = getCache().getCacheTransactionManager();
        MyTransactionListener tl = new MyTransactionListener();
        setTxListener(txMgr2, tl);
        try {
          createRegion(rgnName2);
          getSystem().getLogWriter().info("testTXMultiRegion: Created region2");
        } catch (CacheException e) {
          fail("While creating region", e);
        }
      }
    };
    SerializableRunnable newKey2 = new SerializableRunnable("testTXMultiRegion: Create Key") {
      @Override
      public void run() {
        try {
          Region<?, ?> root = getRootRegion("root");
          Region<String, ?> rgn = root.getSubregion(rgnName2);
          rgn.create("key", null);
          getSystem().getLogWriter().info("testTXMultiRegion: Created Key");
        } catch (CacheException e) {
          fail("While creating region", e);
        }
      }
    };

    SerializableRunnable create3 = new SerializableRunnable("testTXMultiRegion: Create Region") {
      @Override
      public void run() {
        CacheTransactionManager txMgr2 = getCache().getCacheTransactionManager();
        MyTransactionListener tl = new MyTransactionListener();
        setTxListener(txMgr2, tl);
        try {
          createRegion(rgnName3);
          getSystem().getLogWriter().info("testTXMultiRegion: Created Region");
        } catch (CacheException e) {
          fail("While creating region", e);
        }
      }
    };
    SerializableRunnable newKey3 = new SerializableRunnable("testTXMultiRegion: Create Key") {
      @Override
      public void run() {
        try {
          Region<?, ?> root = getRootRegion("root");
          Region<String, ?> rgn = root.getSubregion(rgnName3);
          rgn.create("key", null);
          getSystem().getLogWriter().info("testTXMultiRegion: Created Key");
        } catch (CacheException e) {
          fail("While creating region", e);
        }
      }
    };

    SerializableRunnable check1_3 = new SerializableRunnable("testTXMultiRegion: check") {
      @Override
      public void run() {
        Region<String, String> rgn1 = getRootRegion().getSubregion(rgnName1);
        {
          assertThat(rgn1.getEntry("key")).describedAs("Could not find entry for 'key'")
              .isNotNull();
          assertThat(rgn1.getEntry("key").getValue()).isEqualTo("value1");
        }
        Region<String, String> rgn3 = getRootRegion().getSubregion(rgnName3);
        {
          assertThat(rgn3.getEntry("key")).describedAs("Could not find entry for 'key'")
              .isNotNull();
          assertThat(rgn3.getEntry("key").getValue()).isEqualTo("value3");
        }
        CacheTransactionManager txMgr2 = getCache().getCacheTransactionManager();
        MyTransactionListener tl = firstTransactionListenerFrom(txMgr2);
        tl.checkAfterCommitCount(1);
        assertThat(tl.afterFailedCommitCount).isEqualTo(0);
        assertThat(tl.afterRollbackCount).isEqualTo(0);
        assertThat(tl.closeCount).isEqualTo(0);
        assertThat(tl.lastEvent.getCache()).isEqualTo(rgn1.getRegionService());
        {
          Collection<EntryEvent<?, ?>> events;
          RegionAttributes<String, String> attr = getRegionAttributes();
          if (!attr.getDataPolicy().withReplication() || attr.getConcurrencyChecksEnabled()) {
            events = TxEventTestUtil.getPutEvents(tl.lastEvent.getEvents());
          } else {
            events = TxEventTestUtil.getCreateEvents(tl.lastEvent.getEvents());
          }
          assertThat(events.size()).isEqualTo(2);
          List<EntryEvent<?, ?>> eventList = new ArrayList<>(events);
          eventList.sort((o1, o2) -> {
            String s1 = o1.getRegion().getFullPath() + o1.getKey();
            String s2 = o2.getRegion().getFullPath() + o2.getKey();
            return s1.compareTo(s2);
          });

          verifyMirrorRegionEventsMatch(eventList.get(0), rgn1, "value1");

          verifyMirrorRegionEventsMatch(eventList.get(1), rgn3, "value3");
        }
      }
    };
    SerializableRunnable check2_3 = new SerializableRunnable("testTXMultiRegion: check") {
      @Override
      public void run() {
        Region rgn2 = getRootRegion().getSubregion(rgnName2);
        {
          assertThat(rgn2.getEntry("key")).describedAs("Could not find entry for 'key'")
              .isNotNull();
          assertThat(rgn2.getEntry("key").getValue()).isEqualTo("value2");
        }
        Region rgn3 = getRootRegion().getSubregion(rgnName3);
        {
          assertThat(rgn3.getEntry("key")).describedAs("Could not find entry for 'key'")
              .isNotNull();
          assertThat(rgn3.getEntry("key").getValue()).isEqualTo("value3");
        }
        CacheTransactionManager txMgr2 = getCache().getCacheTransactionManager();
        MyTransactionListener tl = firstTransactionListenerFrom(txMgr2);
        tl.checkAfterCommitCount(1);
        assertThat(tl.afterFailedCommitCount).isEqualTo(0);
        assertThat(tl.afterRollbackCount).isEqualTo(0);
        assertThat(tl.closeCount).isEqualTo(0);
        assertThat(tl.lastEvent.getCache()).isEqualTo(rgn2.getRegionService());
        {
          Collection<EntryEvent<?, ?>> events;
          RegionAttributes attr = getRegionAttributes();
          if (!attr.getDataPolicy().withReplication() || attr.getConcurrencyChecksEnabled()) {
            events = TxEventTestUtil.getPutEvents(tl.lastEvent.getEvents());
          } else {
            events = TxEventTestUtil.getCreateEvents(tl.lastEvent.getEvents());
          }
          assertThat(events.size()).isEqualTo(2);
          List<EntryEvent<?, ?>> eventList = new ArrayList<>(events);
          eventList.sort((o1, o2) -> {
            String s1 = o1.getRegion().getFullPath() + o1.getKey();
            String s2 = o2.getRegion().getFullPath() + o2.getKey();
            return s1.compareTo(s2);
          });

          verifyMirrorRegionEventsMatch(eventList.get(0), rgn2, "value2");

          verifyMirrorRegionEventsMatch(eventList.get(1), rgn3, "value3");

        }
      }
    };
    SerializableRunnable check1 = new SerializableRunnable("testTXMultiRegion: check") {
      @Override
      public void run() {
        Region<String, String> rgn = getRootRegion().getSubregion(rgnName1);
        assertThat(rgn.getEntry("key")).describedAs("Could not find entry for 'key'").isNotNull();
        assertThat(rgn.getEntry("key").getValue()).isEqualTo("value1");
        CacheTransactionManager txMgr2 = getCache().getCacheTransactionManager();
        MyTransactionListener tl = firstTransactionListenerFrom(txMgr2);
        tl.checkAfterCommitCount(1);
        assertThat(tl.afterFailedCommitCount).isEqualTo(0);
        assertThat(tl.afterRollbackCount).isEqualTo(0);
        assertThat(tl.closeCount).isEqualTo(0);
        assertThat(tl.lastEvent.getCache()).isEqualTo(rgn.getRegionService());
        {
          Collection<EntryEvent<?, ?>> events;
          RegionAttributes<String, String> attr = getRegionAttributes();
          if (!attr.getDataPolicy().withReplication() || attr.getConcurrencyChecksEnabled()) {
            events = TxEventTestUtil.getPutEvents(tl.lastEvent.getEvents());
          } else {
            events = TxEventTestUtil.getCreateEvents(tl.lastEvent.getEvents());
          }
          assertThat(events.size()).isEqualTo(1);
          EntryEvent<?, ?> ev = events.iterator().next();
          // assertIndexDetailsEquals(tl.expectedTxId, ev.getTransactionId());
          assertThat(rgn).isSameAs(ev.getRegion());
          assertThat(ev.getKey()).isEqualTo("key");
          assertThat(ev.getNewValue()).isEqualTo("value1");
          assertThat(ev.getOldValue()).isNull();
          assertThat(ev.getOperation().isLocalLoad()).isFalse();
          assertThat(ev.getOperation().isNetLoad()).isFalse();
          assertThat(ev.getOperation().isLoad()).isFalse();
          assertThat(ev.getOperation().isNetSearch()).isFalse();
          assertThat(ev.getOperation().isExpiration()).isFalse();
          assertThat(ev.getCallbackArgument()).isNull();
          assertThat(ev.isCallbackArgumentAvailable()).isTrue();
          assertThat(ev.isOriginRemote()).isTrue();
          assertThat(ev.getOperation().isDistributed()).isTrue();
        }
      }
    };
    SerializableRunnable check2 = new SerializableRunnable("testTXMultiRegion: check") {
      @Override
      public void run() {
        Region<String, String> rgn = getRootRegion().getSubregion(rgnName2);
        assertThat(rgn.getEntry("key")).describedAs("Could not find entry for 'key'").isNotNull();
        assertThat(rgn.getEntry("key").getValue()).isEqualTo("value2");
        CacheTransactionManager txMgr2 = getCache().getCacheTransactionManager();
        MyTransactionListener tl = firstTransactionListenerFrom(txMgr2);
        tl.checkAfterCommitCount(1);
        assertThat(tl.afterFailedCommitCount).isEqualTo(0);
        assertThat(tl.afterRollbackCount).isEqualTo(0);
        assertThat(tl.closeCount).isEqualTo(0);
        assertThat(tl.lastEvent.getCache()).isEqualTo(rgn.getRegionService());
        {
          Collection<EntryEvent<?, ?>> events;
          RegionAttributes<String, String> attr = getRegionAttributes();
          if (!attr.getDataPolicy().withReplication() || attr.getConcurrencyChecksEnabled()) {
            events = TxEventTestUtil.getPutEvents(tl.lastEvent.getEvents());
          } else {
            events = TxEventTestUtil.getCreateEvents(tl.lastEvent.getEvents());
          }
          assertThat(events.size()).isEqualTo(1);
          EntryEvent<?, ?> ev = events.iterator().next();
          assertThat(rgn).isSameAs(ev.getRegion());
          assertThat(ev.getKey()).isEqualTo("key");
          assertThat(ev.getNewValue()).isEqualTo("value2");
          assertThat(ev.getOldValue()).isNull();
          assertThat(ev.getOperation().isLocalLoad()).isFalse();
          assertThat(ev.getOperation().isNetLoad()).isFalse();
          assertThat(ev.getOperation().isLoad()).isFalse();
          assertThat(ev.getOperation().isNetSearch()).isFalse();
          assertThat(ev.getOperation().isExpiration()).isFalse();
          assertThat(ev.getCallbackArgument()).isNull();
          assertThat(ev.isCallbackArgumentAvailable()).isTrue();
          assertThat(ev.isOriginRemote()).isTrue();
          assertThat(ev.getOperation().isDistributed()).isTrue();
        }
      }
    };
    SerializableRunnable check3 = new SerializableRunnable("testTXMultiRegion: check") {
      @Override
      public void run() {
        Region<String, String> rgn = getRootRegion().getSubregion(rgnName3);
        assertThat(rgn.getEntry("key")).describedAs("Could not find entry for 'key'").isNotNull();
        assertThat(rgn.getEntry("key").getValue()).isEqualTo("value3");
        CacheTransactionManager txMgr2 = getCache().getCacheTransactionManager();
        MyTransactionListener tl = firstTransactionListenerFrom(txMgr2);
        tl.checkAfterCommitCount(1);
        assertThat(tl.afterFailedCommitCount).isEqualTo(0);
        assertThat(tl.afterRollbackCount).isEqualTo(0);
        assertThat(tl.closeCount).isEqualTo(0);
        assertThat(tl.lastEvent.getCache()).isEqualTo(rgn.getRegionService());
        {
          Collection<EntryEvent<?, ?>> events;
          RegionAttributes attr = getRegionAttributes();
          if (!attr.getDataPolicy().withReplication() || attr.getConcurrencyChecksEnabled()) {
            events = TxEventTestUtil.getPutEvents(tl.lastEvent.getEvents());
          } else {
            events = TxEventTestUtil.getCreateEvents(tl.lastEvent.getEvents());
          }
          assertThat(events.size()).isEqualTo(1);
          EntryEvent<?, ?> ev = events.iterator().next();
          // assertIndexDetailsEquals(tl.expectedTxId, ev.getTransactionId());
          assertThat(rgn).isSameAs(ev.getRegion());
          assertThat(ev.getKey()).isEqualTo("key");
          assertThat(ev.getNewValue()).isEqualTo("value3");
          assertThat(ev.getOldValue()).isNull();
          assertThat(ev.getOperation().isLocalLoad()).isFalse();
          assertThat(ev.getOperation().isNetLoad()).isFalse();
          assertThat(ev.getOperation().isLoad()).isFalse();
          assertThat(ev.getOperation().isNetSearch()).isFalse();
          assertThat(ev.getOperation().isExpiration()).isFalse();
          assertThat(ev.getCallbackArgument()).isNull();
          assertThat(ev.isCallbackArgumentAvailable()).isTrue();
          assertThat(ev.isOriginRemote()).isTrue();
          assertThat(ev.getOperation().isDistributed()).isTrue();
        }
      }
    };

    VM vm0 = VM.getVM(0);
    VM vm1 = VM.getVM(1);
    VM vm2 = VM.getVM(2);
    VM vm3 = VM.getVM(3);

    try {
      DMStats dmStats = getSystem().getDistributionManager().getStats();
      Region<String, String> rgn1;
      Region<String, String> rgn2;
      Region<String, String> rgn3;
      long cmtMsgs;
      // long sentMsgs;
      long commitWaits;

      // vm0->R1,R3 vm1->R1,R3 vm2->R2 vm3->R2,R3
      vm0.invoke(create1);
      vm0.invoke(newKey1);
      vm0.invoke(create3);
      vm0.invoke(newKey3);

      vm1.invoke(create1);
      vm1.invoke(create3);
      if (!getRegionAttributes().getDataPolicy().withReplication()
          && !getRegionAttributes().getDataPolicy().withPreloaded()) {
        vm1.invoke(newKey1);
        vm1.invoke(newKey3);
      }

      vm2.invoke(create2);
      vm2.invoke(newKey2);

      vm3.invoke(create2);
      vm3.invoke(create3);
      if (!getRegionAttributes().getDataPolicy().withReplication()
          && !getRegionAttributes().getDataPolicy().withPreloaded()) {
        vm3.invoke(newKey2);
        vm3.invoke(newKey3);
      }

      rgn1 = createRegion(rgnName1);
      rgn2 = createRegion(rgnName2);
      rgn3 = createRegion(rgnName3);
      cmtMsgs = dmStats.getSentCommitMessages();
      commitWaits = dmStats.getCommitWaits();

      txMgr.begin();
      rgn1.put("key", "value1");
      rgn2.put("key", "value2");
      rgn3.put("key", "value3");
      // TransactionId txId = txMgr.getTransactionId();
      getSystem().getLogWriter()
          .info("testTXMultiRegion: vm0->R1,R3 vm1->R1,R3 vm2->R2 vm3->R2,R3");
      txMgr.commit();
      assertThat(dmStats.getSentCommitMessages()).isEqualTo(cmtMsgs + 3);
      if (rgn1.getAttributes().getScope().isAck() || rgn2.getAttributes().getScope().isAck()
          || rgn3.getAttributes().getScope().isAck()) {
        assertThat(dmStats.getCommitWaits()).isEqualTo(commitWaits + 1);
      } else {
        assertThat(dmStats.getCommitWaits()).isEqualTo(commitWaits);
        // pause to give cmt message a chance to be processed
        // [bruce] changed from 200 to 2000 for mcast testing
        try {
          Thread.sleep(2000);
        } catch (InterruptedException chomp) {
          fail("interrupted");
        }
      }
      vm0.invoke(check1_3);
      vm1.invoke(check1_3);
      vm2.invoke(check2);
      vm3.invoke(check2_3);
      rgn1.destroyRegion();
      rgn2.destroyRegion();
      rgn3.destroyRegion();

      // vm0->R1,R3 vm1->R1,R3 vm2->R2,R3 vm3->R2,R3
      vm0.invoke(create1);
      vm0.invoke(newKey1);
      vm0.invoke(create3);
      vm0.invoke(newKey3);

      vm1.invoke(create1);
      vm1.invoke(create3);
      if (!getRegionAttributes().getDataPolicy().withReplication()
          && !getRegionAttributes().getDataPolicy().withPreloaded()) {
        vm1.invoke(newKey1);
        vm1.invoke(newKey3);
      }

      vm2.invoke(create2);
      vm2.invoke(newKey2);
      vm2.invoke(create3);
      if (!getRegionAttributes().getDataPolicy().withReplication()
          && !getRegionAttributes().getDataPolicy().withPreloaded()) {
        vm2.invoke(newKey3);
      }

      vm3.invoke(create2);
      vm3.invoke(create3);
      if (!getRegionAttributes().getDataPolicy().withReplication()
          && !getRegionAttributes().getDataPolicy().withPreloaded()) {
        vm3.invoke(newKey2);
        vm3.invoke(newKey3);
      }

      rgn1 = createRegion(rgnName1);
      rgn2 = createRegion(rgnName2);
      rgn3 = createRegion(rgnName3);
      cmtMsgs = dmStats.getSentCommitMessages();
      commitWaits = dmStats.getCommitWaits();

      txMgr.begin();
      rgn1.put("key", "value1");
      rgn2.put("key", "value2");
      rgn3.put("key", "value3");

      getSystem().getLogWriter()
          .info("testTXMultiRegion: vm0->R1,R3 vm1->R1,R3 vm2->R2,R3 vm3->R2,R3");
      txMgr.commit();
      assertThat(dmStats.getSentCommitMessages()).isEqualTo(cmtMsgs + 2);
      if (rgn1.getAttributes().getScope().isAck() || rgn2.getAttributes().getScope().isAck()
          || rgn3.getAttributes().getScope().isAck()) {
        assertThat(dmStats.getCommitWaits()).isEqualTo(commitWaits + 1);
      } else {
        assertThat(dmStats.getCommitWaits()).isEqualTo(commitWaits);
        // pause to give cmt message a chance to be processed
        try {
          Thread.sleep(200);
        } catch (InterruptedException chomp) {
          fail("interrupted");
        }
      }
      vm0.invoke(check1_3);
      vm1.invoke(check1_3);
      vm2.invoke(check2_3);
      vm3.invoke(check2_3);
      rgn1.destroyRegion();
      rgn2.destroyRegion();
      rgn3.destroyRegion();

      // vm0->R1,R3 vm1->R1,R3 vm2->R2 vm3->R1,R3
      vm0.invoke(create1);
      vm0.invoke(newKey1);
      vm0.invoke(create3);
      vm0.invoke(newKey3);

      vm1.invoke(create1);
      vm1.invoke(create3);
      if (!getRegionAttributes().getDataPolicy().withReplication()
          && !getRegionAttributes().getDataPolicy().withPreloaded()) {
        vm1.invoke(newKey1);
        vm1.invoke(newKey3);
      }

      vm2.invoke(create2);
      vm2.invoke(newKey2);

      vm3.invoke(create1);
      vm3.invoke(create3);
      if (!getRegionAttributes().getDataPolicy().withReplication()
          && !getRegionAttributes().getDataPolicy().withPreloaded()) {
        vm3.invoke(newKey1);
        vm3.invoke(newKey3);
      }

      rgn1 = createRegion(rgnName1);
      rgn2 = createRegion(rgnName2);
      rgn3 = createRegion(rgnName3);
      cmtMsgs = dmStats.getSentCommitMessages();
      commitWaits = dmStats.getCommitWaits();

      txMgr.begin();
      rgn1.put("key", "value1");
      rgn2.put("key", "value2");
      rgn3.put("key", "value3");

      getSystem().getLogWriter()
          .info("testTXMultiRegion: vm0->R1,R3 vm1->R1,R3 vm2->R2 vm3->R1,R3");
      txMgr.commit();
      assertThat(dmStats.getSentCommitMessages()).isEqualTo(cmtMsgs + 2);
      if (rgn1.getAttributes().getScope().isAck() || rgn2.getAttributes().getScope().isAck()
          || rgn3.getAttributes().getScope().isAck()) {
        assertThat(dmStats.getCommitWaits()).isEqualTo(commitWaits + 1);
      } else {
        assertThat(dmStats.getCommitWaits()).isEqualTo(commitWaits);
        // pause to give cmt message a chance to be processed
        try {
          Thread.sleep(200);
        } catch (InterruptedException chomp) {
          fail("interrupted");
        }
      }
      vm0.invoke(check1_3);
      vm1.invoke(check1_3);
      vm2.invoke(check2);
      vm3.invoke(check1_3);
      rgn1.destroyRegion();
      rgn2.destroyRegion();
      rgn3.destroyRegion();

      // vm0->R1 vm1->R1 vm2->R2 vm3->R3
      vm0.invoke(create1);
      vm0.invoke(newKey1);

      vm1.invoke(create1);
      if (!getRegionAttributes().getDataPolicy().withReplication()
          && !getRegionAttributes().getDataPolicy().withPreloaded()) {
        vm1.invoke(newKey1);
      }

      vm2.invoke(create2);
      vm2.invoke(newKey2);

      vm3.invoke(create3);
      vm3.invoke(newKey3);

      rgn1 = createRegion(rgnName1);
      rgn2 = createRegion(rgnName2);
      rgn3 = createRegion(rgnName3);
      cmtMsgs = dmStats.getSentCommitMessages();
      commitWaits = dmStats.getCommitWaits();

      txMgr.begin();
      rgn1.put("key", "value1");
      rgn2.put("key", "value2");
      rgn3.put("key", "value3");

      getSystem().getLogWriter().info("testTXMultiRegion: vm0->R1 vm1->R1 vm2->R2 vm3->R3");
      txMgr.commit();
      assertThat(dmStats.getSentCommitMessages()).isEqualTo(cmtMsgs + 3);
      if (rgn1.getAttributes().getScope().isAck() || rgn2.getAttributes().getScope().isAck()
          || rgn3.getAttributes().getScope().isAck()) {
        assertThat(dmStats.getCommitWaits()).isEqualTo(commitWaits + 1);
      } else {
        assertThat(dmStats.getCommitWaits()).isEqualTo(commitWaits);
        // pause to give cmt message a chance to be processed
        try {
          Thread.sleep(200);
        } catch (InterruptedException chomp) {
          fail("interrupted");
        }
      }
      vm0.invoke(check1);
      vm1.invoke(check1);
      vm2.invoke(check2);
      vm3.invoke(check3);
      rgn1.destroyRegion();
      rgn2.destroyRegion();
      rgn3.destroyRegion();

      // vm0->R1,R3 vm1->R2,R3 vm2->R2 vm3->R3
      vm0.invoke(create1);
      vm0.invoke(newKey1);
      vm0.invoke(create3);
      vm0.invoke(newKey3);

      vm1.invoke(create2);
      vm1.invoke(newKey2);
      vm1.invoke(create3);
      if (!getRegionAttributes().getDataPolicy().withReplication()
          && !getRegionAttributes().getDataPolicy().withPreloaded()) {
        vm1.invoke(newKey3);
      }

      vm2.invoke(create2);
      if (!getRegionAttributes().getDataPolicy().withReplication()
          && !getRegionAttributes().getDataPolicy().withPreloaded()) {
        vm2.invoke(newKey2);
      }

      vm3.invoke(create3);
      if (!getRegionAttributes().getDataPolicy().withReplication()
          && !getRegionAttributes().getDataPolicy().withPreloaded()) {
        vm3.invoke(newKey3);
      }

      rgn1 = createRegion(rgnName1);
      rgn2 = createRegion(rgnName2);
      rgn3 = createRegion(rgnName3);
      cmtMsgs = dmStats.getSentCommitMessages();
      commitWaits = dmStats.getCommitWaits();

      txMgr.begin();
      rgn1.put("key", "value1");
      rgn2.put("key", "value2");
      rgn3.put("key", "value3");

      getSystem().getLogWriter().info("testTXMultiRegion: vm0->R1,R3 vm1->R2,R3 vm2->R2 vm3->R3");
      txMgr.commit();
      assertThat(dmStats.getSentCommitMessages()).isEqualTo(cmtMsgs + 4);
      if (rgn1.getAttributes().getScope().isAck() || rgn2.getAttributes().getScope().isAck()
          || rgn3.getAttributes().getScope().isAck()) {
        assertThat(dmStats.getCommitWaits()).isEqualTo(commitWaits + 1);
      } else {
        assertThat(dmStats.getCommitWaits()).isEqualTo(commitWaits);
        // pause to give cmt message a chance to be processed
        try {
          Thread.sleep(200);
        } catch (InterruptedException chomp) {
          fail("interrupted");
        }
      }
      vm0.invoke(check1_3);
      vm1.invoke(check2_3);
      vm2.invoke(check2);
      vm3.invoke(check3);
      rgn1.destroyRegion();
      rgn2.destroyRegion();
      rgn3.destroyRegion();

      // vm0->R1,R3 vm1->R1,R3 vm2->R1,R3 vm3->R1,R3
      vm0.invoke(create1);
      vm0.invoke(newKey1);
      vm0.invoke(create3);
      vm0.invoke(newKey3);

      vm1.invoke(create1);
      if (!getRegionAttributes().getDataPolicy().withReplication()
          && !getRegionAttributes().getDataPolicy().withPreloaded()) {
        vm1.invoke(newKey1);
      }
      vm1.invoke(create3);
      if (!getRegionAttributes().getDataPolicy().withReplication()
          && !getRegionAttributes().getDataPolicy().withPreloaded()) {
        vm1.invoke(newKey3);
      }

      vm2.invoke(create1);
      vm2.invoke(create3);
      if (!getRegionAttributes().getDataPolicy().withReplication()
          && !getRegionAttributes().getDataPolicy().withPreloaded()) {
        vm2.invoke(newKey1);
        vm2.invoke(newKey3);
      }

      vm3.invoke(create1);
      vm3.invoke(create3);
      if (!getRegionAttributes().getDataPolicy().withReplication()
          && !getRegionAttributes().getDataPolicy().withPreloaded()) {
        vm3.invoke(newKey1);
        vm3.invoke(newKey3);
      }

      rgn1 = createRegion(rgnName1);
      rgn2 = createRegion(rgnName2);
      rgn3 = createRegion(rgnName3);
      cmtMsgs = dmStats.getSentCommitMessages();
      commitWaits = dmStats.getCommitWaits();

      txMgr.begin();
      rgn1.put("key", "value1");
      rgn2.put("key", "value2");
      rgn3.put("key", "value3");

      getSystem().getLogWriter()
          .info("testTXMultiRegion: vm0->R1,R3 vm1->R1,R3 vm2->R1,R3 vm3->R1,R3");
      txMgr.commit();
      assertThat(dmStats.getSentCommitMessages()).isEqualTo(cmtMsgs + 1);
      if (rgn1.getAttributes().getScope().isAck() || rgn2.getAttributes().getScope().isAck()
          || rgn3.getAttributes().getScope().isAck()) {
        assertThat(dmStats.getCommitWaits()).isEqualTo(commitWaits + 1);
      } else {
        assertThat(dmStats.getCommitWaits()).isEqualTo(commitWaits);
        // pause to give cmt message a chance to be processed
        try {
          Thread.sleep(200);
        } catch (InterruptedException chomp) {
          fail("interrupted");
        }
      }
      vm0.invoke(check1_3);
      vm1.invoke(check1_3);
      vm2.invoke(check1_3);
      vm3.invoke(check1_3);
      rgn1.destroyRegion();
      rgn2.destroyRegion();
      rgn3.destroyRegion();
    } catch (Exception e) {
      getCache().close();
      getSystem().getLogWriter().fine("testTXMultiRegion: Caused exception in createRegion");
      throw e;
    }
  }

  /**
   * Clear all existing transaction listeners and install the given listener.
   */
  private static void setTxListener(CacheTransactionManager manager,
      TransactionListener listener) {
    Stream.of(manager.getListeners())
        .forEach(manager::removeListener);
    manager.addListener(listener);
  }

  private void verifyMirrorRegionEventsMatch(EntryEvent<?, ?> event, Region region,
      String expectedValue) {
    assertThat(event.getRegion()).isSameAs(region);
    assertThat(event.getKey()).isEqualTo("key");
    assertThat(event.getNewValue()).isEqualTo(expectedValue);
    assertThat(event.getOldValue()).isNull();
    assertThat(event.getOperation().isLocalLoad()).isFalse();
    assertThat(event.getOperation().isNetLoad()).isFalse();
    assertThat(event.getOperation().isLoad()).isFalse();
    assertThat(event.getOperation().isNetSearch()).isFalse();
    assertThat(event.getOperation().isExpiration()).isFalse();
    assertThat(event.getCallbackArgument()).isNull();
    assertThat(event.isCallbackArgumentAvailable()).isTrue();
    assertThat(event.isOriginRemote()).isTrue();
    assertThat(event.getOperation().isDistributed()).isTrue();
  }

  @Test
  public void testTXRmtMirror() {
    assumeThat(supportsTransactions()).isTrue();
    assumeThat(getRegionAttributes().getScope().isGlobal()).isFalse();
    assumeThat(getRegionAttributes().getDataPolicy().withPersistence()).isFalse();

    assertThat(getRegionAttributes().getScope().isDistributed()).isTrue();
    CacheTransactionManager txMgr = this.getCache().getCacheTransactionManager();

    final String rgnName = getUniqueName();

    SerializableRunnable createMirror =
        new SerializableRunnable("textTXRmtMirror: Create Mirrored Region") {
          @Override
          public void run() {
            CacheTransactionManager txMgr2 = getCache().getCacheTransactionManager();
            MyTransactionListener tl = new MyTransactionListener();
            setTxListener(txMgr2, tl);
            try {
              AttributesFactory<?, ?> rgnAtts = new AttributesFactory<>(getRegionAttributes());
              rgnAtts.setDataPolicy(DataPolicy.REPLICATE);
              createRegion(rgnName, rgnAtts.create());
            } catch (CacheException e) {
              fail("While creating region", e);
            }
          }
        };

    SerializableRunnable createNonMirror =
        new SerializableRunnable("textTXRmtMirror: Create Mirrored Region") {
          @Override
          public void run() {
            CacheTransactionManager txMgr2 = getCache().getCacheTransactionManager();
            MyTransactionListener tl = new MyTransactionListener();
            setTxListener(txMgr2, tl);
            try {
              AttributesFactory<?, ?> rgnAtts = new AttributesFactory<>(getRegionAttributes());
              rgnAtts.setDataPolicy(DataPolicy.NORMAL);
              createRegion(rgnName, rgnAtts.create());
            } catch (CacheException e) {
              fail("While creating region", e);
            }
          }
        };

    Region<String, String> region;

    // Make sure that a remote create done in a tx is created in a remote mirror
    // and dropped in a remote non-mirror
    VM vm0 = VM.getVM(0);
    VM vm1 = VM.getVM(1);
    vm0.invoke(createMirror);
    vm1.invoke(createNonMirror);
    region = createRegion(rgnName);

    txMgr.begin();
    region.create("key", "value");
    getSystem().getLogWriter().info("textTXRmtMirror: create mirror and non-mirror");
    txMgr.commit();

    validateTXRmtMirror(rgnName, vm0, vm1);
  }

  private void validateTXRmtMirror(String rgnName, VM vm0, VM vm1) {
    SerializableRunnable checkExists = new SerializableRunnable("textTXRmtMirror: checkExists") {
      @Override
      public void run() {
        Region<String, String> rgn = getRootRegion().getSubregion(rgnName);

        if (!rgn.getAttributes().getScope().isAck()) {
          await().untilAsserted(() -> checkCommitAndDataExists(rgn));
        } else {
          checkCommitAndDataExists(rgn);
        }
      }

      private void checkCommitAndDataExists(Region<String, String> rgn) {
        assertThat(rgn.getEntry("key")).describedAs("Could not find entry for 'key'")
            .isNotNull();
        assertThat(rgn.getEntry("key").getValue()).isEqualTo("value");

        CacheTransactionManager txMgr2 = getCache().getCacheTransactionManager();
        MyTransactionListener tl = firstTransactionListenerFrom(txMgr2);
        tl.assertCounts(1, 0, 0, 0);
        assertThat(tl.lastEvent.getCache()).isEqualTo(rgn.getRegionService());
        List<EntryEvent<?, ?>> events =
            TxEventTestUtil.getCreateEvents(tl.lastEvent.getEvents());
        assertThat(events.size()).isEqualTo(1);
        EntryEvent<?, ?> ev = events.get(0);
        assertThat(rgn).isSameAs(ev.getRegion());
        assertThat(ev.getKey()).isEqualTo("key");
        assertThat(ev.getNewValue()).isEqualTo("value");
        assertThat(ev.getOldValue()).isNull();
        assertThat(ev.getOperation().isLocalLoad()).isFalse();
        assertThat(ev.getOperation().isNetLoad()).isFalse();
        assertThat(ev.getOperation().isLoad()).isFalse();
        assertThat(ev.getOperation().isNetSearch()).isFalse();
        assertThat(ev.getOperation().isExpiration()).isFalse();
        assertThat(ev.getCallbackArgument()).isNull();
        assertThat(ev.isCallbackArgumentAvailable()).isTrue();
        assertThat(ev.isOriginRemote()).isTrue();
        assertThat(ev.getOperation().isDistributed()).isTrue();
      }
    };

    SerializableRunnable checkNoKey = new SerializableRunnable("textTXRmtMirror: checkNoKey") {
      @Override
      public void run() {
        Region<String, String> rgn = getRootRegion().getSubregion(rgnName);

        if (!rgn.getAttributes().getScope().isAck()) {
          await().untilAsserted(() -> {
            checkCommitAndNoData(rgn);
          });
        } else {
          checkCommitAndNoData(rgn);
        }
      }

      private void checkCommitAndNoData(Region<String, String> rgn) {
        assertThat(rgn.getEntry("key")).isNull();
        CacheTransactionManager txMgr2 = getCache().getCacheTransactionManager();
        MyTransactionListener tl = firstTransactionListenerFrom(txMgr2);
        tl.assertCounts(1, 0, 0, 0);
        assertThat(TxEventTestUtil.getCreateEvents(tl.lastEvent.getEvents())).isEmpty();
        assertThat(TxEventTestUtil.getPutEvents(tl.lastEvent.getEvents())).isEmpty();
        assertThat(tl.lastEvent.getCache()).isEqualTo(rgn.getRegionService());
      }
    };

    vm0.invoke(checkExists);
    vm1.invoke(checkNoKey);
  }

  @Ignore("TODO: test is disabled")
  @Test
  public void testTXAlgebra() {
    assumeThat(getRegionAttributes().getScope().isGlobal()).isFalse();
    assumeThat(getRegionAttributes().getDataPolicy().withPersistence()).isFalse();

    assertThat(getRegionAttributes().getScope().isDistributed()).isTrue();

    CacheTransactionManager txMgr = this.getCache().getCacheTransactionManager();
    MyTransactionListener localTl = new MyTransactionListener();
    TransactionId myTXId;
    setTxListener(txMgr, localTl);
    assertThat(localTl.lastEvent).isNull();
    localTl.assertCounts(0, 0, 0, 0);
    final String rgnName = getUniqueName();

    SerializableRunnable create = new SerializableRunnable("testTXAlgebra: Create Region") {
      @Override
      public void run() {
        CacheTransactionManager txMgr2 = getCache().getCacheTransactionManager();
        MyTransactionListener tl = new MyTransactionListener();
        setTxListener(txMgr2, tl);
        assertThat(tl.lastEvent).isNull();
        tl.assertCounts(0, 0, 0, 0);
        try {
          Region<String, Object> rgn = createRegion(rgnName);
          if (!getRegionAttributes().getDataPolicy().withReplication()) {
            rgn.create("key", null);
            getSystem().getLogWriter().info("testTXAlgebra: Created Key");
          }
        } catch (CacheException e) {
          fail("While creating region", e);
        }
      }
    };

    invokeInEveryVM(create);
    // make sure each op sequence has the correct affect transaction event
    // check C + C -> EX
    // check C + P -> C
    try {
      AttributesFactory<String, String> rgnAtts = new AttributesFactory<>(getRegionAttributes());
      rgnAtts.setDataPolicy(DataPolicy.NORMAL);
      Region<String, String> rgn = createRegion(rgnName, rgnAtts.create());

      txMgr.begin();
      myTXId = txMgr.getTransactionId();
      rgn.create("key", "value1");
      assertThatThrownBy(() -> rgn.create("key", "value2"))
          .isInstanceOf(EntryExistsException.class);

      rgn.put("key", "value2");
      assertThat(rgn.getEntry("key").getValue()).isEqualTo("value2");
      txMgr.commit();

      // Make sure commit did not trigger callbacks
      invokeInEveryVM(new CacheSerializableRunnable("testTXAlgebra: check: C+P->C") {
        @Override
        public void run2() {
          Region<String, String> rgn1 = getRootRegion().getSubregion(rgnName);
          CacheTransactionManager txMgr2 = getCache().getCacheTransactionManager();
          MyTransactionListener tl = firstTransactionListenerFrom(txMgr2);

          assertThat(rgn1.getEntry("key").getValue()).isEqualTo("value2");
          tl.assertCounts(1, 0, 0, 0);
          {
            Collection<EntryEvent<?, ?>> events;
            RegionAttributes attr = getRegionAttributes();
            if (!attr.getDataPolicy().withReplication() || attr.getConcurrencyChecksEnabled()) {
              events = TxEventTestUtil.getPutEvents(tl.lastEvent.getEvents());
            } else {
              events = TxEventTestUtil.getCreateEvents(tl.lastEvent.getEvents());
            }
            assertThat(events.size()).isEqualTo(1);
            EntryEvent<?, ?> ev = events.iterator().next();
            assertThat(rgn1).isSameAs(ev.getRegion());
            assertThat(ev.getKey()).isEqualTo("key");
            assertThat(ev.getNewValue()).isEqualTo("value2");
            assertThat(ev.getOldValue()).isNull();
            assertThat(ev.getOperation().isLocalLoad()).isFalse();
            assertThat(ev.getOperation().isNetLoad()).isFalse();
            assertThat(ev.getOperation().isLoad()).isFalse();
            assertThat(ev.getOperation().isNetSearch()).isFalse();
            assertThat(ev.getOperation().isExpiration()).isFalse();
            assertThat(ev.getCallbackArgument()).isNull();
            assertThat(ev.isCallbackArgumentAvailable()).isTrue();
            assertThat(ev.isOriginRemote()).isTrue();
            assertThat(ev.getOperation().isDistributed()).isTrue();
          }
        }
      });
      assertThat(rgn.getEntry("key").getValue()).isEqualTo("value2");
      {
        localTl.assertCounts(1, 0, 0, 0);
        Collection<EntryEvent<?, ?>> events =
            TxEventTestUtil.getCreateEvents(localTl.lastEvent.getEvents());
        assertThat(localTl.lastEvent.getTransactionId()).isEqualTo(myTXId);
        assertThat(events.size()).isEqualTo(1);
        EntryEvent<?, ?> ev = events.iterator().next();
        assertThat(ev.getTransactionId()).isEqualTo(myTXId);
        assertThat(rgn).isSameAs(ev.getRegion());
        assertThat(ev.getKey()).isEqualTo("key");
        assertThat(ev.getNewValue()).isEqualTo("value2");
        assertThat(ev.getOldValue()).isNull();
        assertThat(ev.getOperation().isLocalLoad()).isFalse();
        assertThat(ev.getOperation().isNetLoad()).isFalse();
        assertThat(ev.getOperation().isLoad()).isFalse();
        assertThat(ev.getOperation().isNetSearch()).isFalse();
        assertThat(ev.getCallbackArgument()).isNull();
        assertThat(ev.isCallbackArgumentAvailable()).isTrue();
        assertThat(ev.isOriginRemote()).isFalse();
        assertThat(ev.getOperation().isExpiration()).isFalse();
        assertThat(ev.getOperation().isDistributed()).isTrue();
      }
      if (!getRegionAttributes().getDataPolicy().withReplication()) {
        rgn.invalidate("key");
        rgn.localDestroy("key");
      } else {
        rgn.destroy("key");
      }

      // Check C + DI -> C (invalid value)
      txMgr.begin();
      myTXId = txMgr.getTransactionId();
      rgn.create("key", "value1");

      rgn.invalidate("key");

      assertThat(rgn.containsKey("key")).isTrue();
      assertThat(rgn.containsValueForKey("key")).isFalse();
      txMgr.commit();

      invokeInEveryVM(
          new CacheSerializableRunnable("testTXAlgebra: check: C+DI->C (invalid value)") {
            @Override
            public void run2() {
              Region<String, Object> rgn1 = getRootRegion().getSubregion(rgnName);
              CacheTransactionManager txMgr2 = getCache().getCacheTransactionManager();
              MyTransactionListener tl = firstTransactionListenerFrom(txMgr2);

              assertThat(rgn1.containsKey("key")).isTrue();
              assertThat(rgn1.containsValueForKey("key")).isFalse();
              tl.assertCounts(2, 0, 0, 0);
              {
                Collection<EntryEvent<?, ?>> events;
                RegionAttributes attr = getRegionAttributes();
                if (!attr.getDataPolicy().withReplication() || attr.getConcurrencyChecksEnabled()) {
                  events = TxEventTestUtil.getPutEvents(tl.lastEvent.getEvents());
                } else {
                  events = TxEventTestUtil.getCreateEvents(tl.lastEvent.getEvents());
                }
                assertThat(events.size()).isEqualTo(1);
                EntryEvent<?, ?> ev = events.iterator().next();
                assertThat(rgn1).isSameAs(ev.getRegion());
                assertThat(ev.getKey()).isEqualTo("key");
                assertThat(ev.getNewValue()).isNull();
                assertThat(ev.getOldValue()).isNull();
                assertThat(ev.getOperation().isLocalLoad()).isFalse();
                assertThat(ev.getOperation().isNetLoad()).isFalse();
                assertThat(ev.getOperation().isLoad()).isFalse();
                assertThat(ev.getOperation().isNetSearch()).isFalse();
                assertThat(ev.getOperation().isExpiration()).isFalse();
                assertThat(ev.getCallbackArgument()).isNull();
                assertThat(ev.isCallbackArgumentAvailable()).isTrue();
                assertThat(ev.isOriginRemote()).isTrue();
                assertThat(ev.getOperation().isDistributed()).isTrue();
              }
            }
          });
      assertThat(rgn.containsKey("key")).isTrue();
      assertThat(rgn.containsValueForKey("key")).isFalse();
      localTl.assertCounts(2, 0, 0, 0);
      {
        Collection<EntryEvent<?, ?>> events =
            TxEventTestUtil.getCreateEvents(localTl.lastEvent.getEvents());
        assertThat(localTl.lastEvent.getTransactionId()).isEqualTo(myTXId);
        assertThat(events.size()).isEqualTo(1);
        EntryEvent<?, ?> ev = events.iterator().next();
        assertThat(ev.getTransactionId()).isEqualTo(myTXId);
        assertThat(rgn).isSameAs(ev.getRegion());
        assertThat(ev.getKey()).isEqualTo("key");
        assertThat(ev.getNewValue()).isNull();
        assertThat(ev.getOldValue()).isNull();
        assertThat(ev.getOperation().isLocalLoad()).isFalse();
        assertThat(ev.getOperation().isNetLoad()).isFalse();
        assertThat(ev.getOperation().isLoad()).isFalse();
        assertThat(ev.getOperation().isNetSearch()).isFalse();
        assertThat(ev.getCallbackArgument()).isNull();
        assertThat(ev.isCallbackArgumentAvailable()).isTrue();
        assertThat(ev.isOriginRemote()).isFalse();
        assertThat(ev.getOperation().isExpiration()).isFalse();
        assertThat(ev.getOperation().isDistributed()).isTrue();
      }

      // check (commited) LI + DI -> NOOP
      assertThat(rgn.containsKey("key")).isTrue();
      assertThat(rgn.containsValueForKey("key")).isFalse();
      txMgr.begin();
      rgn.invalidate("key");
      assertThat(rgn.containsKey("key")).isTrue();
      assertThat(rgn.containsValueForKey("key")).isFalse();
      txMgr.commit();
      invokeInEveryVM(
          new CacheSerializableRunnable("testTXAlgebra: check: committed LI + TX DI-> NOOP") {
            @Override
            public void run2() {
              Region rgn1 = getRootRegion().getSubregion(rgnName);
              CacheTransactionManager txMgr2 = getCache().getCacheTransactionManager();
              MyTransactionListener tl = firstTransactionListenerFrom(txMgr2);

              assertThat(rgn1.getEntry("key").getValue()).isEqualTo("value1");
              tl.assertCounts(2, 0, 0, 0); // There should be no change in counts
            }
          });
      assertThat(rgn.containsKey("key")).isTrue();
      assertThat(rgn.containsValueForKey("key")).isFalse();
      localTl.assertCounts(2, 0, 0, 0); // There should be no change in counts

      // @todo mitch
      // check DI + LI -> DI
      // check DI + DI -> DI

      if (!getRegionAttributes().getDataPolicy().withReplication()) {
        // check (exists commited) LI + DI -> LI
        rgn.put("key", "value1");
        assertThat(rgn.containsKey("key")).isTrue();
        assertThat(rgn.getEntry("key").getValue()).isEqualTo("value1");
        txMgr.begin();
        myTXId = txMgr.getTransactionId();
        rgn.localInvalidate("key");
        rgn.invalidate("key");
        assertThat(rgn.containsKey("key")).isTrue();
        assertThat(rgn.containsValueForKey("key")).isFalse();
        txMgr.commit();
        invokeInEveryVM(
            new CacheSerializableRunnable("testTXAlgebra: check: TX LI + TX DI -> LI") {
              @Override
              public void run2() {
                Region rgn1 = getRootRegion().getSubregion(rgnName);
                CacheTransactionManager txMgr2 = getCache().getCacheTransactionManager();
                MyTransactionListener tl = firstTransactionListenerFrom(txMgr2);
                assertThat(rgn1.containsKey("key")).isTrue();
                assertThat(rgn1.containsValueForKey("key")).isTrue();
                assertThat(rgn1.getEntry("key").getValue()).isEqualTo("value1");
                tl.assertCounts(2, 0, 0, 0); // nothing happened remotely
              }
            });
        assertThat(rgn.containsKey("key")).isTrue();
        assertThat(rgn.containsValueForKey("key")).isFalse();
        assertThat(rgn.getEntry("key").getValue()).isNull();
        localTl.assertCounts(3, 0, 0, 0);
        {
          Collection<EntryEvent<?, ?>> events =
              TxEventTestUtil.getInvalidateEvents(localTl.lastEvent.getEvents());
          assertThat(events.size()).isEqualTo(1);
          EntryEvent<?, ?> ev = events.iterator().next();
          assertThat(ev.getTransactionId()).isEqualTo(myTXId);
          assertThat(rgn).isSameAs(ev.getRegion());
          assertThat(ev.getKey()).isEqualTo("key");
          assertThat(ev.getNewValue()).isNull();
          assertThat(ev.getOldValue()).isEqualTo("value1");
          assertThat(ev.getOperation().isLocalLoad()).isFalse();
          assertThat(ev.getOperation().isNetLoad()).isFalse();
          assertThat(ev.getOperation().isLoad()).isFalse();
          assertThat(ev.getOperation().isNetSearch()).isFalse();
          assertThat(ev.getCallbackArgument()).isNull();
          assertThat(ev.isCallbackArgumentAvailable()).isTrue();
          assertThat(ev.isOriginRemote()).isFalse();
          assertThat(ev.getOperation().isExpiration()).isFalse();
          assertThat(ev.getOperation().isDistributed()).isTrue();
        }

        rgn.invalidate("key");
        rgn.localDestroy("key");
      } else {
        rgn.destroy("key");
      }

      // check C + DD -> DD
      //// callbackVal.reset();
      txMgr.begin();
      rgn.create("key", "value0");
      rgn.destroy("key");
      assertThat(rgn.containsKey("key")).isFalse();
      txMgr.commit();
      invokeInEveryVM(new CacheSerializableRunnable("testTXAlgebra: check: C+DD->DD") {
        @Override
        public void run2() {
          Region<String, Object> rgn1 = getRootRegion().getSubregion(rgnName);
          CacheTransactionManager txMgr2 = getCache().getCacheTransactionManager();
          MyTransactionListener tl = firstTransactionListenerFrom(txMgr2);

          assertThat(rgn1.containsKey("key")).isFalse();
          assertThat(rgn1.containsValueForKey("key")).isFalse();
          tl.assertCounts(3, 0, 0, 0);
          {
            Collection<EntryEvent<?, ?>> events =
                TxEventTestUtil.getDestroyEvents(tl.lastEvent.getEvents());
            assertThat(events.size()).isEqualTo(1);
            EntryEvent<?, ?> ev = events.iterator().next();
            assertThat(rgn1).isSameAs(ev.getRegion());
            assertThat(ev.getKey()).isNull();
            assertThat(ev.getNewValue()).isNull();
            assertThat(ev.getOldValue()).isNull();
            assertThat(ev.getOperation().isLocalLoad()).isFalse();
            assertThat(ev.getOperation().isNetLoad()).isFalse();
            assertThat(ev.getOperation().isLoad()).isFalse();
            assertThat(ev.getOperation().isNetSearch()).isFalse();
            assertThat(ev.getOperation().isExpiration()).isFalse();
            assertThat(ev.getCallbackArgument()).isNull();
            assertThat(ev.isCallbackArgumentAvailable()).isTrue();
            assertThat(ev.isOriginRemote()).isTrue();
            assertThat(ev.getOperation().isDistributed()).isTrue();
          }
        }
      });
      assertThat(rgn.containsKey("key")).isFalse();
      localTl.assertCounts(3, 0, 0, 0); // no change

      // Check C + LI -> C
      if (!getRegionAttributes().getDataPolicy().withReplication()) {
        // assume that remote regions have same mirror type as local
        invokeInEveryVM(new CacheSerializableRunnable("testTXAlgebra: C+LI-> entry creation") {
          @Override
          public void run2() {
            Region<String, ?> rgn1 = getRootRegion().getSubregion(rgnName);
            try {
              rgn1.create("key", null);
            } catch (CacheException e) {
              fail("While creating key", e);
            }
          }
        });
      }
      assertThat(rgn.containsKey("key")).isFalse();
      txMgr.begin();
      myTXId = txMgr.getTransactionId();
      rgn.create("key", "value1");
      rgn.localInvalidate("key");
      assertThat(rgn.containsKey("key")).isTrue();
      assertThat(rgn.containsValueForKey("key")).isFalse();
      txMgr.commit();
      invokeInEveryVM(
          new CacheSerializableRunnable("testTXAlgebra: check: C+LI->C (with value)") {
            @Override
            public void run2() {
              Region<String, String> rgn1 = getRootRegion().getSubregion(rgnName);
              CacheTransactionManager txMgr2 = getCache().getCacheTransactionManager();
              MyTransactionListener tl = firstTransactionListenerFrom(txMgr2);
              tl.assertCounts(4, 0, 0, 0);
              assertThat(rgn1.containsKey("key")).isTrue();
              assertThat(rgn1.getEntry("key").getValue()).isEqualTo("value1");
              {
                Collection<EntryEvent<?, ?>> events;
                RegionAttributes attr = getRegionAttributes();
                if (!attr.getDataPolicy().withReplication() || attr.getConcurrencyChecksEnabled()) {
                  events = TxEventTestUtil.getPutEvents(tl.lastEvent.getEvents());
                } else {
                  events = TxEventTestUtil.getCreateEvents(tl.lastEvent.getEvents());
                }
                assertThat(events.size()).isEqualTo(1);
                EntryEvent<?, ?> ev = events.iterator().next();
                assertThat(rgn1).isSameAs(ev.getRegion());
                assertThat(ev.getKey()).isEqualTo("key");
                assertThat(ev.getNewValue()).isEqualTo("value1");
                assertThat(ev.getOldValue()).isNull();
                assertThat(ev.getOperation().isLocalLoad()).isFalse();
                assertThat(ev.getOperation().isNetLoad()).isFalse();
                assertThat(ev.getOperation().isLoad()).isFalse();
                assertThat(ev.getOperation().isNetSearch()).isFalse();
                assertThat(ev.getOperation().isExpiration()).isFalse();
                assertThat(ev.getCallbackArgument()).isNull();
                assertThat(ev.isCallbackArgumentAvailable()).isTrue();
                assertThat(ev.isOriginRemote()).isTrue();
                assertThat(ev.getOperation().isDistributed()).isTrue();
              }
            }
          });
      assertThat(rgn.containsKey("key")).isTrue();
      assertThat(rgn.containsValueForKey("key")).isFalse();
      localTl.assertCounts(4, 0, 0, 0);
      {
        Collection<EntryEvent<?, ?>> events =
            TxEventTestUtil.getCreateEvents(localTl.lastEvent.getEvents());
        assertThat(localTl.lastEvent.getTransactionId()).isEqualTo(myTXId);
        assertThat(events.size()).isEqualTo(1);
        EntryEvent<?, ?> ev = events.iterator().next();
        assertThat(ev.getTransactionId()).isEqualTo(myTXId);
        assertThat(rgn).isSameAs(ev.getRegion());
        assertThat(ev.getKey()).isEqualTo("key");
        assertThat(ev.getNewValue()).isNull();
        assertThat(ev.getOldValue()).isNull();
        assertThat(ev.getOperation().isLocalLoad()).isFalse();
        assertThat(ev.getOperation().isNetLoad()).isFalse();
        assertThat(ev.getOperation().isLoad()).isFalse();
        assertThat(ev.getOperation().isNetSearch()).isFalse();
        assertThat(ev.getCallbackArgument()).isNull();
        assertThat(ev.isCallbackArgumentAvailable()).isTrue();
        assertThat(ev.isOriginRemote()).isFalse();
        assertThat(ev.getOperation().isExpiration()).isFalse();
        assertThat(ev.getOperation().isDistributed()).isTrue();
      }
      rgn.destroy("key");

      // Check P + LI + C -> EX
      // Check C + LI + P -> C
      //// callbackVal.reset();
      txMgr.begin();
      myTXId = txMgr.getTransactionId();
      rgn.create("key", "value1");
      rgn.localInvalidate("key");

      assertThatThrownBy(() -> rgn.create("key", "ex")).isInstanceOf(EntryExistsException.class);

      rgn.put("key", "value2");
      assertThat(rgn.containsKey("key")).isTrue();
      assertThat(rgn.getEntry("key").getValue()).isEqualTo("value2");
      txMgr.commit();

      assertThat(rgn.containsKey("key")).isTrue();
      assertThat(rgn.getEntry("key").getValue()).isEqualTo("value2");
      localTl.assertCounts(5, 0, 0, 0);
      {
        Collection<EntryEvent<?, ?>> events =
            TxEventTestUtil.getCreateEvents(localTl.lastEvent.getEvents());
        assertThat(localTl.lastEvent.getTransactionId()).isEqualTo(myTXId);
        assertThat(events.size()).isEqualTo(1);
        EntryEvent<?, ?> ev = events.iterator().next();
        assertThat(ev.getTransactionId()).isEqualTo(myTXId);
        assertThat(rgn).isSameAs(ev.getRegion());
        assertThat(ev.getKey()).isEqualTo("key");
        assertThat(ev.getNewValue()).isEqualTo("value2");
        assertThat(ev.getOldValue()).isNull();
        assertThat(ev.getOperation().isLocalLoad()).isFalse();
        assertThat(ev.getOperation().isNetLoad()).isFalse();
        assertThat(ev.getOperation().isLoad()).isFalse();
        assertThat(ev.getOperation().isNetSearch()).isFalse();
        assertThat(ev.getCallbackArgument()).isNull();
        assertThat(ev.isCallbackArgumentAvailable()).isTrue();
        assertThat(ev.isOriginRemote()).isFalse();
        assertThat(ev.getOperation().isExpiration()).isFalse();
        assertThat(ev.getOperation().isDistributed()).isTrue();
      }
      rgn.localDestroy("key");

    } catch (Exception e) {
      getCache().close();
      getSystem().getLogWriter().fine("testTXAlgebra: Caused exception in createRegion");
      throw e;
    }

  }

  //////////////////////////////////////////////////////////////////////////////////////
  // M E T H O D S F O R V E R S I O N I N G F O L L O W
  //////////////////////////////////////////////////////////////////////////////////////

  /**
   * return the region attributes for the given type of region. See
   * GemFireCache.getRegionAttributes(String).
   * Subclasses are expected to reimplement this method. See
   * DistributedAckRegionCCEDUnitTest.getRegionAttributes(String).
   */
  protected <K, V> RegionAttributes<K, V> getRegionAttributes(String type) {
    throw new IllegalStateException("subclass must reimplement this method");
  }

  /*
   * This test creates a server cache in vm0 and a peer cache in vm1. It then tests to see if GII
   * transferred tombstones to vm1 like it's supposed to. A client cache is created in vm2 and the
   * same sort of check is performed for register-interest.
   */

  public void versionTestGIISendsTombstones() {
    VM vm0 = VM.getVM(0);
    VM vm1 = VM.getVM(1);
    final int serverPort = AvailablePortHelper.getRandomAvailableTCPPort();

    // create replicated regions in VM 0 and 1, then perform concurrent ops
    // on the same key while creating the region in VM2. Afterward make
    // sure that all three regions are consistent

    final String name = this.getUniqueName() + "-CC";
    SerializableRunnable createRegion = new SerializableRunnable("Create Region") {
      @Override
      public void run() {
        try {
          RegionFactory<?, ?> f = getCache().createRegionFactory(getRegionAttributes());
          CCRegion = (LocalRegion) f.create(name);
          if (VM.getCurrentVMNum() == 0) {
            CacheServer bridge = CCRegion.getCache().addCacheServer();
            bridge.setPort(serverPort);
            try {
              bridge.start();
            } catch (IOException ex) {
              fail("While creating bridge", ex);
            }
          }
        } catch (CacheException ex) {
          fail("While creating region", ex);
        }
      }
    };

    SerializableRunnable asserter = new SerializableRunnable("ensure tombstone has been received") {
      @Override
      public void run() {
        RegionEntry entry = CCRegion.getRegionEntry("object2");
        assertThat(entry).isNotNull();
        assertThat(entry.isTombstone()).isTrue();
      }
    };

    vm0.invoke(createRegion);
    vm0.invoke(new SerializableRunnable("create some tombstones") {
      @Override
      public void run() {
        CCRegion.put("object1", "value1");
        CCRegion.put("object2", "value2");
        CCRegion.put("object3", "value3");
        CCRegion.destroy("object2");
      }
    });

    try {
      vm0.invoke(asserter);
      vm1.invoke(createRegion);
      vm1.invoke(asserter);

    } finally {
      disconnectAllFromDS();
    }
  }

  /**
   * This tests the concurrency versioning system to ensure that event conflation happens correctly
   * and that the statistic is being updated properly
   */
  public void versionTestConcurrentEvents() throws Exception {
    VM vm0 = VM.getVM(0);
    VM vm1 = VM.getVM(1);
    VM vm2 = VM.getVM(2);

    // create replicated regions in VM 0 and 1, then perform concurrent ops
    // on the same key while creating the region in VM2. Afterward make
    // sure that all three regions are consistent

    final String name = this.getUniqueName() + "-CC";
    SerializableRunnable createRegion = new SerializableRunnable("Create Region") {
      @Override
      public void run() {
        try {
          RegionFactory f = getCache().createRegionFactory(getRegionAttributes());
          CCRegion = (LocalRegion) f.create(name);
        } catch (CacheException ex) {
          fail("While creating region", ex);
        }
      }
    };

    vm0.invoke(createRegion);
    vm1.invoke(createRegion);

    SerializableRunnable performOps = new SerializableRunnable("perform concurrent ops") {
      @Override
      public void run() {
        try {
          doOpsLoop(5000, false);
          long events = CCRegion.getCachePerfStats().getConflatedEventsCount();
          if (!CCRegion.getScope().isGlobal()) {
            assertThat(events > 0).describedAs("expected some event conflation").isTrue();
          }
        } catch (CacheException e) {
          fail("while performing concurrent operations", e);
        }
      }
    };

    AsyncInvocation a0 = vm0.invokeAsync(performOps);
    AsyncInvocation a1 = vm1.invokeAsync(performOps);

    try {
      Thread.sleep(500);
    } catch (InterruptedException e) {
      fail("sleep was interrupted");
    }

    vm2.invoke(createRegion);

    boolean a0failed = waitForAsyncProcessing(a0, "expected some event conflation");
    boolean a1failed = waitForAsyncProcessing(a1, "expected some event conflation");

    if (a0failed && a1failed) {
      fail("neither member saw event conflation - check stats for " + name);
    }

    // check consistency of the regions
    Map r0Contents = vm0.invoke(MultiVMRegionTestCase::getCCRegionContents);
    Map r1Contents = vm1.invoke(MultiVMRegionTestCase::getCCRegionContents);
    Map r2Contents = vm2.invoke(MultiVMRegionTestCase::getCCRegionContents);

    for (int i = 0; i < 10; i++) {
      String key = "cckey" + i;
      assertThat(r1Contents.get(key)).describedAs("region contents are not consistent for " + key)
          .isEqualTo(
              r0Contents.get(key));
      assertThat(r2Contents.get(key)).describedAs("region contents are not consistent for " + key)
          .isEqualTo(
              r1Contents.get(key));
      for (int subi = 1; subi < 3; subi++) {
        String subkey = key + "-" + subi;
        if (r0Contents.containsKey(subkey)) {
          assertThat(r1Contents.get(subkey)).describedAs(
              "region contents are not consistent for " + subkey).isEqualTo(r0Contents.get(subkey));
          assertThat(r2Contents.get(subkey)).describedAs(
              "region contents are not consistent for " + subkey).isEqualTo(r1Contents.get(subkey));
        } else {
          assertThat(r1Contents.containsKey(subkey)).isFalse();
        }
      }
    }

    // now we move on to testing deltas

    if (!getRegionAttributes().getScope().isDistributedNoAck()) { // no-ack doesn't support deltas
      vm0.invoke(MultiVMRegionTestCase::clearCCRegion);

      performOps = new SerializableRunnable("perform concurrent delta ops") {
        @Override
        public void run() {
          try {
            long stopTime = System.currentTimeMillis() + 5000;
            Random ran = new Random(System.currentTimeMillis());
            while (System.currentTimeMillis() < stopTime) {
              for (int i = 0; i < 10; i++) {
                CCRegion.put("cckey" + i, new DeltaValue("ccvalue" + ran.nextInt()));
              }
            }
            long events = CCRegion.getCachePerfStats().getDeltaFailedUpdates();
            assertThat(events > 0).describedAs("expected some failed deltas").isTrue();
          } catch (CacheException e) {
            fail("while performing concurrent operations", e);
          }
        }
      };

      a0 = vm0.invokeAsync(performOps);
      a1 = vm1.invokeAsync(performOps);

      a0failed = waitForAsyncProcessing(a0, "expected some failed deltas");
      a1failed = waitForAsyncProcessing(a1, "expected some failed deltas");

      if (a0failed && a1failed) {
        fail("neither member saw failed deltas - check stats for " + name);
      }

      // check consistency of the regions
      r0Contents = vm0.invoke(MultiVMRegionTestCase::getCCRegionContents);
      r1Contents = vm1.invoke(MultiVMRegionTestCase::getCCRegionContents);
      r2Contents = vm2.invoke(MultiVMRegionTestCase::getCCRegionContents);

      for (int i = 0; i < 10; i++) {
        String key = "cckey" + i;
        assertThat(r1Contents.get(key)).describedAs("region contents are not consistent").isEqualTo(
            r0Contents.get(key));
        assertThat(r2Contents.get(key)).describedAs("region contents are not consistent").isEqualTo(
            r1Contents.get(key));
        for (int subi = 1; subi < 3; subi++) {
          String subkey = key + "-" + subi;
          if (r0Contents.containsKey(subkey)) {
            assertThat(r1Contents.get(subkey)).describedAs("region contents are not consistent")
                .isEqualTo(
                    r0Contents.get(subkey));
            assertThat(r2Contents.get(subkey)).describedAs("region contents are not consistent")
                .isEqualTo(
                    r1Contents.get(subkey));
          } else {
            assertThat(r1Contents.containsKey(subkey)).isFalse();
          }
        }
      }

      // The region version vectors should now all be consistent with the version stamps in the
      // entries.

      List<RegionVersionVector<VersionSource<?>>> versionVectors = new ArrayList<>();
      List<InternalDistributedMember> vmIds = new ArrayList<>();
      List<Map<String, VersionTag<VersionSource<?>>>> versions = new ArrayList<>();

      for (VM vm : Arrays.asList(vm0, vm1, vm2)) {
        vmIds.add(vm.invoke(MultiVMRegionTestCase::getMemberId));
        versionVectors.add(getVersionVector(vm));
        versions.add(vm.invoke(MultiVMRegionTestCase::getCCRegionVersions));
      }

      for (int i = 0; i < versions.size(); i++) {
        compareVersions(versions.get(0), vmIds.get(0), vmIds, versionVectors);
      }
    }
  }

  private void compareVersions(Map<String, VersionTag<VersionSource<?>>> versions,
      InternalDistributedMember defaultID,
      List<InternalDistributedMember> vmIds,
      List<RegionVersionVector<VersionSource<?>>> versionVectors) {
    for (Map.Entry<String, VersionTag<VersionSource<?>>> entry : versions.entrySet()) {
      VersionTag<VersionSource<?>> tag = entry.getValue();
      tag.replaceNullIDs(defaultID);
      for (int i = 0; i < vmIds.size(); i++) {
        assertThat(versionVectors.get(i).contains(tag.getMemberID(), tag.getRegionVersion()))
            .describedAs(
                vmIds.get(i) + " should contain " + tag)
            .isTrue();
      }
    }
  }

  private RegionVersionVector<VersionSource<?>> getVersionVector(VM vm) throws Exception {
    byte[] serializedForm = vm.invoke(MultiVMRegionTestCase::getCCRegionVersionVector);
    DataInputStream dis = new DataInputStream(new ByteArrayInputStream(serializedForm));
    return (RegionVersionVector<VersionSource<?>>) DataSerializer.readObject(dis);
  }

  private AsyncInvocation performOps4ClearWithConcurrentEvents(VM vm, final int msToRun) {
    SerializableRunnable performOps = new SerializableRunnable("perform concurrent ops") {
      @Override
      public void run() {
        try {
          doOpsLoop(msToRun, true);
        } catch (CacheException e) {
          fail("while performing concurrent operations", e);
        }
      }
    };
    return vm.invokeAsync(performOps);
  }

  protected void createRegionWithAttribute(VM vm, final String name, final boolean syncDiskWrite) {
    SerializableRunnable createRegion = new SerializableRunnable("Create Region") {
      @Override
      public void run() {
        try {
          RegionFactory f = getCache().createRegionFactory(getRegionAttributes());
          f.setDiskSynchronous(syncDiskWrite);
          CCRegion = (LocalRegion) f.create(name);
        } catch (CacheException ex) {
          fail("While creating region", ex);
        }
      }
    };
    vm.invoke(createRegion);
  }

  public void versionTestClearWithConcurrentEvents() {
    versionTestClearWithConcurrentEvents(true);
  }

  public void versionTestClearWithConcurrentEventsAsync() {
    versionTestClearWithConcurrentEvents(false);
  }

  private void versionTestClearWithConcurrentEvents(boolean syncDiskWrite) {
    VM vm0 = VM.getVM(0);
    VM vm1 = VM.getVM(1);
    VM vm2 = VM.getVM(2);

    // create replicated regions in VM 0 and 1, then perform concurrent ops
    // on the same key while creating the region in VM2. Afterward make
    // sure that all three regions are consistent

    final String name = this.getUniqueName() + "-CC";
    createRegionWithAttribute(vm0, name, syncDiskWrite);
    createRegionWithAttribute(vm1, name, syncDiskWrite);

    AsyncInvocation a0 = performOps4ClearWithConcurrentEvents(vm0, 5000);
    AsyncInvocation a1 = performOps4ClearWithConcurrentEvents(vm1, 5000);

    try {
      Thread.sleep(500);
    } catch (InterruptedException e) {
      fail("sleep was interrupted");
    }

    createRegionWithAttribute(vm2, name, syncDiskWrite);

    waitForAsyncProcessing(a0, "");
    waitForAsyncProcessing(a1, "");

    // check consistency of the regions
    Map r0Contents = vm0.invoke(MultiVMRegionTestCase::getCCRegionContents);
    Map r1Contents = vm1.invoke(MultiVMRegionTestCase::getCCRegionContents);
    Map r2Contents = vm2.invoke(MultiVMRegionTestCase::getCCRegionContents);

    for (int i = 0; i < 10; i++) {
      String key = "cckey" + i;
      assertThat(r1Contents.get(key)).describedAs("region contents are not consistent").isEqualTo(
          r0Contents.get(key));
      assertThat(r2Contents.get(key)).describedAs("region contents are not consistent").isEqualTo(
          r1Contents.get(key));
      for (int subi = 1; subi < 3; subi++) {
        String subkey = key + "-" + subi;
        if (r0Contents.containsKey(subkey)) {
          assertThat(r1Contents.get(subkey)).describedAs("region contents are not consistent")
              .isEqualTo(
                  r0Contents.get(subkey));
          assertThat(r2Contents.get(subkey)).describedAs("region contents are not consistent")
              .isEqualTo(
                  r1Contents.get(subkey));
        } else {
          boolean condition = !r1Contents.containsKey(subkey);
          assertThat(condition).describedAs("expected containsKey(" + subkey + ") to return false")
              .isTrue();
        }
      }
    }

    vm0.invoke(MultiVMRegionTestCase::assertNoClearTimeouts);
    vm1.invoke(MultiVMRegionTestCase::assertNoClearTimeouts);
    vm2.invoke(MultiVMRegionTestCase::assertNoClearTimeouts);
  }

  public void versionTestClearOnNonReplicateWithConcurrentEvents() {
    VM vm0 = VM.getVM(0);
    VM vm1 = VM.getVM(1);
    VM vm2 = VM.getVM(2);
    VM vm3 = VM.getVM(3);

    // create replicated regions in VM 0 and 1, then perform concurrent ops
    // on the same key while creating the region in VM2. Afterward make
    // sure that all three regions are consistent

    final String name = this.getUniqueName() + "-CC";
    SerializableRunnable createRegion = new SerializableRunnable("Create Region") {
      @Override
      public void run() {
        try {
          RegionFactory<?, ?> f;
          if (VM.getCurrentVMNum() == 0) {
            f = getCache().createRegionFactory(
                getRegionAttributes(RegionShortcut.REPLICATE_PROXY.toString()));
          } else if (VM.getCurrentVMNum() == 1) {
            f = getCache().createRegionFactory(getRegionAttributes());
            f.setDataPolicy(DataPolicy.NORMAL);
          } else {
            f = getCache().createRegionFactory(getRegionAttributes());
          }
          CCRegion = (LocalRegion) f.create(name);
        } catch (CacheException ex) {
          fail("While creating region", ex);
        }
      }
    };

    vm0.invoke(createRegion); // empty region
    vm1.invoke(createRegion); // "normal" region
    vm2.invoke(createRegion); // replicate
    vm3.invoke(createRegion); // replicate

    SerializableRunnable performOps = new SerializableRunnable("perform concurrent ops") {
      @Override
      public void run() {
        try {
          doOpsLoop(5000, true);
        } catch (CacheException e) {
          fail("while performing concurrent operations", e);
        }
        if (CCRegion.getScope().isDistributedNoAck()) {
          sendSerialMessageToAll(); // flush the ops
        }
      }
    };

    AsyncInvocation a0 = vm0.invokeAsync(performOps);
    AsyncInvocation a1 = vm1.invokeAsync(performOps);

    try {
      Thread.sleep(500);
    } catch (InterruptedException e) {
      fail("sleep was interrupted");
    }

    waitForAsyncProcessing(a0, "");
    waitForAsyncProcessing(a1, "");

    // check consistency of the regions
    Map r2Contents = vm2.invoke(MultiVMRegionTestCase::getCCRegionContents); // replicated
    Map r3Contents = vm3.invoke(MultiVMRegionTestCase::getCCRegionContents); // replicated

    for (int i = 0; i < 10; i++) {
      String key = "cckey" + i;
      // because datapolicy=normal regions do not accept ops when an entry is not present
      // they may miss invalidates/creates/destroys that other VMs see while applying ops
      // that they originate that maybe should have been elided. For this reason we can't
      // guarantee their consistency and don't check for it here.
      assertThat(r3Contents.get(key)).describedAs("region contents are not consistent for " + key)
          .isEqualTo(
              r2Contents.get(key));
      for (int subi = 1; subi < 3; subi++) {
        String subkey = key + "-" + subi;
        if (r2Contents.containsKey(subkey)) {
          assertThat(r3Contents.get(subkey)).describedAs(
              "region contents are not consistent for " + subkey).isEqualTo(r2Contents.get(subkey));
        }
      }
    }
    // vm0 has no storage, but the others should have hit no timeouts waiting for
    // their region version vector to dominate the vector sent with the clear() operation.
    // If they did, then some ops were not properly recorded in the vector and something
    // is broken.
    vm1.invoke(MultiVMRegionTestCase::assertNoClearTimeouts);
    vm2.invoke(MultiVMRegionTestCase::assertNoClearTimeouts);
    vm3.invoke(MultiVMRegionTestCase::assertNoClearTimeouts);
  }

  private void checkCCRegionTombstoneCount(String msg, int expected) {
    int actual = CCRegion.getTombstoneCount();
    if (expected != actual) {
      assertThat(actual)
          .describedAs(msg + " region tombstone count was " + actual + " expected=" + expected
              + " TombstoneService=" + CCRegion.getCache().getTombstoneService())
          .isEqualTo(expected);
    }
  }

  private void waitForAllTombstonesToExpire(int initialTombstoneCount) {
    try {

      await()
          .until(() -> CCRegion.getTombstoneCount() == 0);
    } catch (ConditionTimeoutException timeout) {
      fail("Timed out waiting for all tombstones to expire.  There are now "
          + CCRegion.getTombstoneCount() + " tombstones left out of " + initialTombstoneCount
          + " initial tombstones. " + CCRegion.getCache().getTombstoneService(), timeout);
    }
  }

  public void versionTestTombstones() {
    disconnectAllFromDS();
    VM vm0 = VM.getVM(0);
    VM vm1 = VM.getVM(1);
    final int numEntries = 100;

    // create replicated regions in VM 0 and 1, then perform concurrent ops
    // on the same key while creating the region in VM2. Afterward make
    // sure that all three regions are consistent
    final long oldServerTimeout = TombstoneService.REPLICATE_TOMBSTONE_TIMEOUT;
    final long oldClientTimeout = TombstoneService.NON_REPLICATE_TOMBSTONE_TIMEOUT;
    final int oldExpiredTombstoneLimit = TombstoneService.EXPIRED_TOMBSTONE_LIMIT;
    final boolean oldIdleExpiration = TombstoneService.IDLE_EXPIRATION;
    final double oldLimit = TombstoneService.GC_MEMORY_THRESHOLD;
    final long oldMaxSleepTime = TombstoneService.MAX_SLEEP_TIME;
    try {
      SerializableRunnable setTimeout = new SerializableRunnable() {
        @Override
        public void run() {
          TombstoneService.REPLICATE_TOMBSTONE_TIMEOUT = 1000;
          TombstoneService.NON_REPLICATE_TOMBSTONE_TIMEOUT = 900;
          TombstoneService.EXPIRED_TOMBSTONE_LIMIT = numEntries;
          TombstoneService.IDLE_EXPIRATION = true;
          TombstoneService.GC_MEMORY_THRESHOLD = 0; // turn this off so heap profile won't cause
          // test to fail
          TombstoneService.MAX_SLEEP_TIME = 500;
        }
      };
      vm0.invoke(setTimeout);
      vm1.invoke(setTimeout);
      final String name = this.getUniqueName() + "-CC";
      SerializableRunnable createRegion = new SerializableRunnable("Create Region") {
        @Override
        public void run() {
          try {
            RegionFactory f = getCache().createRegionFactory(getRegionAttributes());
            CCRegion = (LocalRegion) f.create(name);
            for (int i = 0; i < numEntries; i++) {
              CCRegion.put("cckey" + i, "ccvalue");
            }
            if (CCRegion.getScope().isDistributedNoAck()) {
              sendSerialMessageToAll(); // flush the ops
            }
          } catch (CacheException ex) {
            fail("While creating region", ex);
          }
        }
      };

      vm0.invoke(createRegion);
      vm1.invoke(createRegion);

      vm0.invoke(new SerializableRunnable("destroy entries and check tombstone count") {
        @Override
        public void run() {
          try {
            for (int i = 0; i < numEntries; i++) {
              CCRegion.destroy("cckey" + i);
              boolean condition1 = !CCRegion.containsKey("cckey" + i);
              assertThat(condition1).describedAs("entry should not exist").isTrue();
              boolean condition = !CCRegion.containsValueForKey("cckey" + i);
              assertThat(condition).describedAs("entry should not contain a value").isTrue();
            }
            checkCCRegionTombstoneCount("after destroys in this vm ", numEntries);
            boolean condition = !CCRegion.containsValue(Token.TOMBSTONE);
            assertThat(condition).describedAs("region should not contain a tombstone").isTrue();
            if (CCRegion.getScope().isDistributedNoAck()) {
              sendSerialMessageToAll(); // flush the ops
            }
          } catch (CacheException e) {
            fail("while performing destroy operations", e);
          }
        }
      });

      vm1.invoke(new SerializableRunnable("check tombstone count(2)") {
        @Override
        public void run() {
          checkCCRegionTombstoneCount("after destroys in other vm ", numEntries);
          try {
            waitForAllTombstonesToExpire(numEntries);
          } catch (ConditionTimeoutException e) {
            CCRegion.dumpBackingMap();
            logger.info("tombstone service state: " + CCRegion.getCache().getTombstoneService());
            throw e;
          }
        }
      });

      vm0.invoke(new SerializableRunnable("create/destroy entries and check tombstone count") {
        @Override
        public void run() {
          final int origCount = CCRegion.getTombstoneCount();
          try {
            waitForAllTombstonesToExpire(origCount);
            logger.debug("creating tombstones.  current count={}", CCRegion.getTombstoneCount());
            for (int i = 0; i < numEntries; i++) {
              CCRegion.create("cckey" + i, i);
              CCRegion.destroy("cckey" + i);
            }
            logger.debug("done creating tombstones.  current count={}",
                CCRegion.getTombstoneCount());
            checkCCRegionTombstoneCount("after create+destroy in this vm ", numEntries);
            assertThat(CCRegion.size()).isEqualTo(0);
            afterCreates = 0;
            AttributesMutator<Object, Object> m = attributesMutatorFor(CCRegion);
            m.addCacheListener(new CacheListenerAdapter<Object, Object>() {
              @Override
              public void afterCreate(EntryEvent<Object, Object> event) {
                afterCreates++;
              }
            });
            if (CCRegion.getScope().isDistributedNoAck()) {
              sendSerialMessageToAll(); // flush the ops
            }
          } catch (AssertionError e) {
            CCRegion.dumpBackingMap();
            logger.info("tombstone service state: " + CCRegion.getCache().getTombstoneService());
            throw e;
          } catch (CacheException e) {
            fail("while performing create/destroy operations", e);
          }
        }
      });

      vm1.invoke(new SerializableRunnable("check tombstone count and install listener") {
        @Override
        public void run() {
          checkCCRegionTombstoneCount("after create+destroy in other vm ", numEntries);
          afterCreates = 0;
          AttributesMutator<Object, Object> m = attributesMutatorFor(CCRegion);
          m.addCacheListener(new CacheListenerAdapter<Object, Object>() {
            @Override
            public void afterCreate(EntryEvent<Object, Object> event) {
              afterCreates++;
            }
          });
        }
      });

      // Now check to see if tombstones are resurrected by a create.
      // The entries should be created okay and the callback should be afterCreate.
      // The tombstone count won't go down until the entries are swept, but then
      // the count should fall to zero.

      vm0.invoke(
          new SerializableRunnable("create entries and check afterCreate and tombstone count") {
            @Override
            public void run() {
              try {
                for (int i = 0; i < numEntries; i++) {
                  CCRegion.create("cckey" + i, i);
                }
                checkCCRegionTombstoneCount("after create in this vm", 0);
                assertThat(afterCreates).describedAs("expected " + numEntries + " afterCreates")
                    .isEqualTo(
                        numEntries);
                assertThat(CCRegion.size()).isEqualTo(numEntries);
                if (CCRegion.getScope().isDistributedNoAck()) {
                  sendSerialMessageToAll(); // flush the ops
                }

                await()
                    .until(
                        () -> CCRegion.getCache().getTombstoneService()
                            .getScheduledTombstoneCount() == 0);

              } catch (CacheException e) {
                fail("while performing create operations", e);
              } catch (ConditionTimeoutException timeout) {
                fail("Timed out waiting for all scheduled tombstones to be removed.  There are now "
                    + CCRegion.getCache().getTombstoneService().getScheduledTombstoneCount()
                    + " tombstones left out of " + numEntries + " initial tombstones. "
                    + CCRegion.getCache().getTombstoneService(), timeout);
              }
            }
          });

      vm1.invoke(new SerializableRunnable("check afterCreate and tombstone count") {
        @Override
        public void run() {
          checkCCRegionTombstoneCount("after create in other vm", 0);
          assertThat(afterCreates).describedAs("expected " + numEntries + " afterCreates")
              .isEqualTo(
                  numEntries);
          assertThat(CCRegion.size()).isEqualTo(numEntries);
          try {
            await()
                .until(() -> CCRegion.getCache().getTombstoneService()
                    .getScheduledTombstoneCount() == 0);
          } catch (ConditionTimeoutException timeout) {
            String message =
                "Timed out waiting for all scheduled tombstones to be removed.  There are now "
                    + CCRegion.getCache().getTombstoneService().getScheduledTombstoneCount()
                    + " tombstones left out of " + numEntries + " initial tombstones. "
                    + CCRegion.getCache().getTombstoneService();
            fail(message, timeout);
          }
        }
      });
    } finally {
      SerializableRunnable resetTimeout = new SerializableRunnable() {
        @Override
        public void run() {
          TombstoneService.REPLICATE_TOMBSTONE_TIMEOUT = oldServerTimeout;
          TombstoneService.NON_REPLICATE_TOMBSTONE_TIMEOUT = oldClientTimeout;
          TombstoneService.EXPIRED_TOMBSTONE_LIMIT = oldExpiredTombstoneLimit;
          TombstoneService.IDLE_EXPIRATION = oldIdleExpiration;
          TombstoneService.GC_MEMORY_THRESHOLD = oldLimit;
          TombstoneService.MAX_SLEEP_TIME = oldMaxSleepTime;
        }
      };
      vm0.invoke(resetTimeout);
      vm1.invoke(resetTimeout);
    }
  }

  /**
   * This tests the concurrency versioning system to ensure that event conflation happens correctly
   * and that the statistic is being updated properly
   */
  public void versionTestConcurrentEventsOnEmptyRegion() {
    VM vm0 = VM.getVM(0);
    VM vm1 = VM.getVM(1);
    VM vm2 = VM.getVM(2);
    VM vm3 = VM.getVM(3); // this VM, but treat as a remote for uniformity

    // create an empty region in vm0 and replicated regions in VM 1 and 3,
    // then perform concurrent ops
    // on the same key while creating the region in VM2. Afterward make
    // sure that all three regions are consistent

    final String name = this.getUniqueName() + "-CC";
    SerializableRunnable createRegion = new SerializableRunnable("Create Region") {
      @Override
      public void run() {
        // set log-level to fine so we'll see InitialImageOperation keys in the log for
        // GEODE-6326
        System.setProperty(DistributionConfig.LOG_LEVEL_NAME, "fine");
        try {
          final RegionFactory<?, ?> f;
          if (VM.getCurrentVMNum() == 0) {
            f = getCache().createRegionFactory(
                getRegionAttributes(RegionShortcut.REPLICATE_PROXY.toString()));
          } else {
            if (VM.getCurrentVMNum() == 2) {
              InitialImageOperation.slowImageProcessing = 1;
            }
            f = getCache().createRegionFactory(getRegionAttributes());
          }
          CCRegion = (LocalRegion) f.create(name);
        } catch (CacheException ex) {
          fail("While creating region", ex);
        } finally {
          System.setProperty(DistributionConfig.LOG_LEVEL_NAME, DUnitLauncher.logLevel);
        }
      }
    };

    vm0.invoke(createRegion);
    vm1.invoke(createRegion);
    vm3.invoke(createRegion);

    SerializableRunnable performOps = new SerializableRunnable("perform concurrent ops") {
      @Override
      public void run() {
        try {
          doOpsLoop(5000, false);
          // This send serial message is only going to flush the operations
          // from the empty member to *one* of the replicas, not all of them.
          sendSerialMessageToAll();
          if (CCRegion.getAttributes().getDataPolicy().withReplication()) {
            long events = CCRegion.getCachePerfStats().getConflatedEventsCount();
            assertThat(events > 0).describedAs("expected some event conflation").isTrue();
          }
        } catch (CacheException e) {
          fail("while performing concurrent operations", e);
        }
      }
    };

    AsyncInvocation a0 = vm0.invokeAsync(performOps);
    AsyncInvocation a1 = vm1.invokeAsync(performOps);

    try {
      Thread.sleep(500);
    } catch (InterruptedException e) {
      fail("sleep was interrupted");
    }

    vm2.invoke(createRegion);

    boolean a0failed = waitForAsyncProcessing(a0, "expected some event conflation");
    boolean a1failed = waitForAsyncProcessing(a1, "expected some event conflation");

    if (a0failed && a1failed) {
      fail("neither member saw event conflation - check stats for " + name);
    }

    // For no-ack regions, messages may still be in flight between replicas at this point
    try {
      await("Wait for the members to eventually be consistent")
          .untilAsserted(() -> {

            // check consistency of the regions
            Map r1Contents = vm1.invoke(MultiVMRegionTestCase::getCCRegionContents);
            Map r2Contents = vm2.invoke(MultiVMRegionTestCase::getCCRegionContents);
            Map r3Contents = vm3.invoke(MultiVMRegionTestCase::getCCRegionContents);

            for (int i = 0; i < 10; i++) {
              String key = "cckey" + i;
              assertThat(r2Contents.get(key)).describedAs(
                  "r2 contents are not consistent with r1 for " + key)
                  .isEqualTo(r1Contents.get(key));
              assertThat(r3Contents.get(key)).describedAs(
                  "r3 contents are not consistent with r2 for " + key)
                  .isEqualTo(r2Contents.get(key));
              for (int subi = 1; subi < 3; subi++) {
                String subkey = key + "-" + subi;
                if (r1Contents.containsKey(subkey)) {
                  assertThat(r2Contents.get(subkey)).describedAs(
                      "r2 contents are not consistent with r1 for subkey " + subkey).isEqualTo(
                          r1Contents.get(subkey));
                  assertThat(r3Contents.get(subkey)).describedAs(
                      "r3 contents are not consistent with r2 for subkey " + subkey).isEqualTo(
                          r2Contents.get(subkey));
                } else {
                  assertThat(r2Contents.containsKey(subkey))
                      .describedAs("r2 contains subkey " + subkey + " that r1 does not").isFalse();
                  assertThat(r3Contents.containsKey(subkey))
                      .describedAs("r3 contains subkey " + subkey + " that r1 does not").isFalse();
                }
              }
            }
          });
    } finally {
      vm1.invoke("dump region contents", () -> CCRegion.dumpBackingMap());
      vm2.invoke("dump region contents", () -> {
        CCRegion.dumpBackingMap();
        InitialImageOperation.slowImageProcessing = 0;
      });
      vm3.invoke("dump region contents", () -> CCRegion.dumpBackingMap());
    }
  }

  private void doOpsLoop(int runTimeMs, boolean includeClear) {
    doOpsLoopNoFlush(runTimeMs, includeClear, true);
    if (CCRegion.getScope().isDistributedNoAck()) {
      sendSerialMessageToAll(); // flush the ops
    }
  }


  public static void doOpsLoopNoFlush(int runTimeMs, boolean includeClear, boolean includePutAll) {
    long stopTime = System.currentTimeMillis() + runTimeMs;
    Random ran = new Random(System.currentTimeMillis());
    String key = null;
    String value = null;
    String oldkey;
    String oldvalue;
    while (System.currentTimeMillis() < stopTime) {
      for (int i = 0; i < 10; i++) {
        oldkey = key;
        oldvalue = value;
        int v = ran.nextInt();
        key = "cckey" + i;
        value = "ccvalue" + v;
        try {
          switch (v & 0x7) {
            case 0:
              CCRegion.put(key, value);
              break;
            case 1:
              if (CCRegion.getAttributes().getDataPolicy().withReplication()) {
                if (oldkey != null) {
                  CCRegion.replace(oldkey, oldvalue, value);
                }
                break;
              } // else fall through to putAll
              //$FALL-THROUGH$
            case 2:
              v = ran.nextInt();
              // too many putAlls make this test run too long
              if (includePutAll && (v & 0x7) < 3) {
                Map<String, String> map = new HashMap<>();
                map.put(key, value);
                map.put(key + "-1", value);
                map.put(key + "-2", value);
                CCRegion.putAll(map, "putAllCallback");
              } else {
                CCRegion.put(key, value);
              }
              break;
            case 3:
              if (CCRegion.getAttributes().getDataPolicy().withReplication()) {
                // since we have a known key/value pair that was used before,
                // use the oldkey/oldvalue for remove(k,v)
                if (oldkey != null) {
                  CCRegion.remove(oldkey, oldvalue);
                }
                break;
              } // else fall through to destroy
              //$FALL-THROUGH$
            case 4:
              CCRegion.destroy(key);
              break;
            case 5:
              if (includeClear) {
                CCRegion.clear();
                break;
              } else {
                if (CCRegion.getAttributes().getDataPolicy().withReplication()) {
                  if (oldkey != null) {
                    CCRegion.putIfAbsent(oldkey, value);
                  }
                  break;
                } // else fall through to invalidate
              }
              //$FALL-THROUGH$
            case 6:
              CCRegion.invalidate(key);
              break;
          }
        } catch (EntryNotFoundException e) {
          // expected
        }
      }
    }
  }

  /**
   * This tests the concurrency versioning system to ensure that event conflation happens correctly
   * and that the statistic is being updated properly
   */
  public void versionTestConcurrentEventsOnNonReplicatedRegion() {

    VM vm0 = VM.getVM(0);
    VM vm1 = VM.getVM(1);
    VM vm2 = VM.getVM(2);
    VM vm3 = VM.getVM(3); // this VM, but treat as a remote for uniformity
    final boolean noAck = !getRegionAttributes().getScope().isAck();

    // create an empty region in vm0 and replicated regions in VM 1 and 3,
    // then perform concurrent ops
    // on the same key while creating the region in VM2. Afterward make
    // sure that all three regions are consistent

    final String name = this.getUniqueName() + "-CC";
    SerializableRunnable createRegion = new SerializableRunnable("Create Region") {
      @Override
      public void run() {
        try {
          final RegionFactory<?, ?> f;
          if (VM.getCurrentVMNum() == 0) {
            f = getCache()
                .createRegionFactory(getRegionAttributes(RegionShortcut.LOCAL.toString()));
            f.setScope(getRegionAttributes().getScope());
          } else {
            f = getCache().createRegionFactory(getRegionAttributes());
          }
          CCRegion = (LocalRegion) f.create(name);
        } catch (CacheException ex) {
          fail("While creating region", ex);
        }
      }
    };

    vm0.invoke(createRegion);
    vm1.invoke(createRegion);
    vm3.invoke(createRegion);

    SerializableRunnable performOps = new SerializableRunnable("perform concurrent ops") {
      @Override
      public void run() {
        try {
          doOpsLoop(5000, false);
          sendSerialMessageToAll();
          if (CCRegion.getAttributes().getDataPolicy().withReplication()) {
            long events = CCRegion.getCachePerfStats().getConflatedEventsCount();
            assertThat(events > 0).describedAs("expected some event conflation").isTrue();
          }
        } catch (CacheException e) {
          fail("while performing concurrent operations", e);
        }
      }
    };

    AsyncInvocation a0 = vm0.invokeAsync(performOps);
    AsyncInvocation a1 = vm1.invokeAsync(performOps);

    try {
      Thread.sleep(500);
    } catch (InterruptedException e) {
      fail("sleep was interrupted");
    }

    vm2.invoke(createRegion);

    boolean a0failed = waitForAsyncProcessing(a0, "expected some event conflation");
    boolean a1failed = waitForAsyncProcessing(a1, "expected some event conflation");

    if (a0failed && a1failed) {
      fail("neither member saw event conflation - check stats for " + name);
    }

    // check consistency of the regions
    Map r0Contents = vm0.invoke(MultiVMRegionTestCase::getCCRegionContents);
    Map r1Contents = vm1.invoke(MultiVMRegionTestCase::getCCRegionContents);
    Map r2Contents = vm2.invoke(MultiVMRegionTestCase::getCCRegionContents);
    Map r3Contents = vm3.invoke(MultiVMRegionTestCase::getCCRegionContents);

    for (int i = 0; i < 10; i++) {
      String key = "cckey" + i;
      assertThat(r2Contents.get(key)).describedAs("region contents are not consistent").isEqualTo(
          r1Contents.get(key));
      assertThat(r3Contents.get(key)).describedAs("region contents are not consistent").isEqualTo(
          r2Contents.get(key));
      for (int subi = 1; subi < 3; subi++) {
        String subkey = key + "-" + subi;
        if (r1Contents.containsKey(subkey)) {
          assertThat(r2Contents.get(subkey)).describedAs("region contents are not consistent")
              .isEqualTo(
                  r1Contents.get(subkey));
          assertThat(r3Contents.get(subkey)).describedAs("region contents are not consistent")
              .isEqualTo(
                  r2Contents.get(subkey));
          if (r0Contents.containsKey(subkey)) {
            assertThat(r0Contents.get(subkey)).describedAs("region contents are not consistent")
                .isEqualTo(
                    r1Contents.get(subkey));
          }
        } else {
          assertThat(r2Contents.containsKey(subkey)).isFalse();
          assertThat(r3Contents.containsKey(subkey)).isFalse();
          assertThat(r0Contents.containsKey(subkey)).isFalse();
        }
      }
    }

    // a non-replicate region should not carry tombstones, so we'll check for that.
    // then we'll use a cache loader and make sure that 1-hop is used to put the
    // entry into the cache in a replicate. The new entry should have a version
    // of 1 when it's first created, the tombstone should have version 2 and
    // the loaded value should have version 3
    final String loadKey = "loadKey";
    vm0.invoke(new SerializableRunnable("add cache loader and create destroyed entry") {
      @Override
      public void run() {
        AttributesMutator<Object, Object> attributesMutator = attributesMutatorFor(CCRegion);
        attributesMutator.setCacheLoader(new CacheLoader<Object, Object>() {
          @Override
          public void close() {}

          @Override
          public Object load(LoaderHelper<Object, Object> helper) throws CacheLoaderException {
            logger.info("The test CacheLoader has been invoked for key '" + helper.getKey() + "'");
            return "loadedValue";
          }
        });

        CCRegion.put(loadKey, "willbeLoadedInitialValue");
        CCRegion.destroy(loadKey);
        if (noAck) { // flush for validation to work
          sendSerialMessageToAll();
        }
        // this assertion guarantees that non-replicated regions do not create tombstones.
        // this is currently not the case but is an open issue
        // assertTrue(CCRegion.getRegionEntry(loadKey) == null);
      }
    });
    vm1.invoke(new SerializableRunnable("confirm tombstone") {
      @Override
      public void run() {
        assertThat(CCRegion.getRegionEntry(loadKey).getValueInVM(CCRegion)).isSameAs(
            Token.TOMBSTONE);
      }
    });
    vm0.invoke(new SerializableRunnable("use cache loader") {
      @Override
      public void run() {
        assertThat(CCRegion.get(loadKey)).isEqualTo("loadedValue");
        assertThat((CCRegion.getRegionEntry(loadKey)).getVersionStamp().getEntryVersion())
            .isEqualTo(
                (long) 3);
      }
    });
    if (!noAck) { // might be 3 or 4 with no-ack
      vm1.invoke(new SerializableRunnable("verify version number") {
        @Override
        public void run() {
          assertThat(CCRegion.get(loadKey)).isEqualTo("loadedValue");
          assertThat((CCRegion.getRegionEntry(loadKey)).getVersionStamp().getEntryVersion())
              .isEqualTo(
                  (long) 3);
        }
      });
    }
  }

  public void versionTestGetAllWithVersions() {
    // this test has timing issues in no-ack
    assumeThat(getRegionAttributes().getScope().isAck()).isTrue();
    // scopes

    VM vm0 = VM.getVM(0);
    VM vm1 = VM.getVM(1);

    final String regionName = getUniqueName() + "CCRegion";
    SerializableRunnable createRegion = new SerializableRunnable("Create Region") {
      @Override
      public void run() {
        try {
          final RegionFactory<?, ?> f;
          if (VM.getCurrentVMNum() == 0) {
            f = getCache()
                .createRegionFactory(getRegionAttributes(RegionShortcut.LOCAL.toString()));
            f.setScope(getRegionAttributes().getScope());
          } else {
            f = getCache().createRegionFactory(getRegionAttributes());
          }
          CCRegion = (LocalRegion) f.create(regionName);
        } catch (CacheException ex) {
          fail("While creating region", ex);
        }
      }
    };

    vm0.invoke(createRegion);
    vm1.invoke(createRegion);
    vm1.invoke(new SerializableRunnable("Populate region and perform some ops") {
      @Override
      public void run() {
        for (int i = 0; i < 100; i++) {
          CCRegion.put("cckey" + i, i);
        }
        for (int i = 0; i < 100; i++) {
          CCRegion.put("cckey" + i, i + 1);
        }
      }
    });

    vm0.invoke(new SerializableRunnable("Perform getAll") {
      @Override
      public void run() {
        List<String> keys = new LinkedList<>();
        for (int i = 0; i < 100; i++) {
          keys.add("cckey" + i);
        }
        @SuppressWarnings("unchecked")
        Map<String, Object> result = (Map<String, Object>) CCRegion.getAll(keys);
        assertThat(keys.size()).isEqualTo(result.size());
        LocalRegion r = CCRegion;
        for (int i = 0; i < 100; i++) {
          RegionEntry entry = r.getRegionEntry("cckey" + i);
          int stamp = entry.getVersionStamp().getEntryVersion();
          logger.info("checking key cckey" + i + " having version " + stamp + " entry=" + entry);
          assertThat(stamp).isEqualTo(2);
          assertThat(i + 1).isEqualTo(result.get("cckey" + i));
        }
      }
    });
  }

  boolean waitForAsyncProcessing(AsyncInvocation async, String expectedError) {
    try {
      async.getResult();
    } catch (Throwable e) {
      assertThat(hasCauseMessage(e, expectedError)).isTrue();
    }
    return false;
  }

  /**
   * The number of milliseconds to try repeating validation code in the event that AssertionError is
   * thrown. For ACK scopes, no repeat should be necessary.
   */
  protected long getRepeatTimeoutMs() {
    return 0;
  }

  private static void assertNoClearTimeouts() {
    // if there are timeouts on waiting for version vector dominance then
    // some operation was not properly recorded in the VM throwing this
    // assertion error. All ops need to be recorded in the version vector
    assertThat(CCRegion.getCachePerfStats().getClearTimeouts()).describedAs(
        "expected there to be no timeouts - something is broken").isEqualTo(0);
  }

  private static void clearCCRegion() {
    CCRegion.clear();
  }

  @SuppressWarnings("unchecked")
  public static Map getCCRegionContents() {
    return new HashMap<>(CCRegion);
  }

  /**
   * Since version vectors aren't java.io.Serializable we use DataSerializer to return a serialized
   * form of the vector
   */
  private static byte[] getCCRegionVersionVector() throws Exception {
    Object id = getMemberId();
    int vm = VM.getCurrentVMNum();
    logger.info(
        "vm" + vm + " with id " + id + " copying " + CCRegion.getVersionVector().fullToString());
    RegionVersionVector vector = CCRegion.getVersionVector().getCloneForTransmission();
    logger.info("clone is " + vector);
    HeapDataOutputStream dos = new HeapDataOutputStream(3000, Version.CURRENT);
    DataSerializer.writeObject(vector, dos);
    byte[] bytes = dos.toByteArray();
    logger.info("serialized size is " + bytes.length);
    return bytes;
  }

  /**
   * returns a map of keys->versiontags for the test region
   */
  private static Map<String, VersionTag<VersionSource<?>>> getCCRegionVersions() {
    Map<String, VersionTag<VersionSource<?>>> result = new HashMap<>();
    @SuppressWarnings("unchecked")
    Map<String, Object> regionAsMap = (Map<String, Object>) CCRegion;
    for (String key : regionAsMap.keySet()) {
      result.put(key, CCRegion.getRegionEntry(key).getVersionStamp().asVersionTag());
    }
    return result;
  }

  private static InternalDistributedMember getMemberId() {
    return CCRegion.getDistributionManager().getDistributionManagerId();
  }

  private void sendSerialMessageToAll() {
    if (getCache() instanceof GemFireCacheImpl) {
      try {
        org.apache.geode.distributed.internal.SerialAckedMessage msg =
            new org.apache.geode.distributed.internal.SerialAckedMessage();
        msg.send(getCache().getDistributionManager().getNormalDistributionManagerIds(), false);
      } catch (Exception e) {
        throw new RuntimeException("Unable to send serial message due to exception", e);
      }
    }
  }

  /**
   * a class for testing handling of concurrent delta operations
   */
  static class DeltaValue implements org.apache.geode.Delta, Serializable {

    private String value;

    @SuppressWarnings("unused") // Required for deserialization
    public DeltaValue() {}

    DeltaValue(String value) {
      this.value = value;
    }

    @Override
    public boolean hasDelta() {
      return true;
    }

    @Override
    public void toDelta(DataOutput out) throws IOException {
      out.writeUTF(this.value);
    }

    @Override
    public void fromDelta(DataInput in) throws IOException, InvalidDeltaException {
      this.value = in.readUTF();
    }

    @Override
    public int hashCode() {
      return this.value.hashCode();
    }

    @Override
    public boolean equals(Object obj) {
      if (!(obj instanceof DeltaValue)) {
        return false;
      }
      return this.value.equals(((DeltaValue) obj).value);
    }

    @Override
    public String toString() {
      return this.value;
    }

  }

  @SuppressWarnings("unchecked")
  private static <L extends TransactionListener> L firstTransactionListenerFrom(
      CacheTransactionManager transactionManager) {
    TransactionListener[] listeners = transactionManager.getListeners();
    assertThat(listeners).describedAs("Listeners on transactionManager for transaction with id "
        + transactionManager.getTransactionId()).hasSize(1);
    return (L) listeners[0];
  }

  @SuppressWarnings("unchecked")
  private static <A extends AttributesMutator> A attributesMutatorFor(LocalRegion region) {
    return (A) region.getAttributesMutator();
  }

  /**
   * Decorates the given runnable to make it repeat every {@link #POLL_INTERVAL_MILLIS} until either
   * it terminates without throwing or the test's repeat timeout expires. If the test's repeat
   * timeout (obtained by calling {@link #getRepeatTimeoutMs()}) is less than or equal to {@code
   * POLL_INTERVAL_MILLIS}, the given runnable is returned undecorated.
   *
   * @param runnable the runnable to run
   */
  private SerializableRunnableIF repeatingIfNecessary(SerializableRunnableIF runnable) {
    return repeatingIfNecessary(getRepeatTimeoutMs(), runnable);
  }

  /**
   * Decorates the given runnable to make it repeat every {@link #POLL_INTERVAL_MILLIS} until either
   * it terminates without throwing or the given timeout expires. If the timeout is less than or
   * equal to {@code POLL_INTERVAL_MILLIS}, the given runnable is returned undecorated.
   *
   * @param timeoutMillis the maximum length of time (in milliseconds) to repeat the runnable
   * @param runnable the runnable to run
   */
  private static SerializableRunnableIF repeatingIfNecessary(long timeoutMillis,
      SerializableRunnableIF runnable) {
    if (timeoutMillis > POLL_INTERVAL_MILLIS) {
      return () -> await()
          .untilAsserted(runnable::run);
    }
    return runnable;
  }
}
