@Test
  public void test014InvalidateAndDestroyPropagation() throws CacheException {
    final String name = getName();

    vm0.invoke("Create Cache Server", () -> {
      RegionFactory<Object, Object> factory = getBridgeServerRegionAttributes(null, null);
      createRegion(name, factory);
      startBridgeServer(0);

    });
    final int port = vm0.invoke(ConnectionPoolDUnitTest::getCacheServerPort);
    final String host0 = NetworkUtils.getServerHostName();

    vm1.invoke("Create region", new CacheSerializableRunnable() {
      @Override
      public void run2() throws CacheException {
        getLonerSystem();
        getCache();
        RegionFactory<Object, Object> factory = getCache().createRegionFactory();
        factory.setScope(Scope.LOCAL);
        factory.setConcurrencyChecksEnabled(false);
        configureConnectionPool(factory, host0, new int[] {port}, true, -1, -1, null);
        factory.addCacheListener(new CertifiableTestCacheListener<>());
        Region rgn = createRegion(name, factory);
        rgn.registerInterestRegex(".*", false, false);
      }
    });
    vm1.invoke("Populate region", () -> {
      Region<Object, Object> region = getRootRegion().getSubregion(name);
      for (int i = 0; i < 10; i++) {
        region.put(i, "old" + i);
      }
    });
    vm2.invoke("Create region", new CacheSerializableRunnable() {
      @Override
      public void run2() throws CacheException {
        getLonerSystem();
        getCache();
        RegionFactory<Object, Object> factory = getCache().createRegionFactory();
        factory.setScope(Scope.LOCAL);
        factory.setConcurrencyChecksEnabled(false);
        configureConnectionPool(factory, host0, new int[] {port}, true, -1, -1, null);
        factory.addCacheListener(new CertifiableTestCacheListener<>());
        Region rgn = createRegion(name, factory);
        rgn.registerInterestRegex(".*", false, false);
      }
    });

    vm1.invoke("Turn on history", () -> {
      await().until(() -> getRootRegion().getSubregion(name) != null);
      Region<Object, Object> region = getRootRegion().getSubregion(name);
      CertifiableTestCacheListener<Object, Object> ctl =
          (CertifiableTestCacheListener<Object, Object>) region.getAttributes()
              .getCacheListeners()[0];
      ctl.enableEventHistory();
    });

    vm2.invoke("Update region", () -> {
      Region<Object, Object> region = getRootRegion().getSubregion(name);
      for (int i = 0; i < 10; i++) {
        region.put(i, "new" + i, "callbackArg" + i);
      }
    });

    vm1.invoke("Verify invalidates", () -> {
      Region<Object, Object> region = getRootRegion().getSubregion(name);
      CertifiableTestCacheListener<Object, Object> ctl =
          (CertifiableTestCacheListener<Object, Object>) region.getAttributes()
              .getCacheListeners()[0];

      for (int i = 0; i < 10; i++) {
        Object key = i;
        ctl.waitForInvalidated(key);
        Region.Entry entry = region.getEntry(key);
        assertThat(entry).isNotNull();
        assertThat(entry.getValue()).isNull();
      }

      List<CacheEvent<Object, Object>> list = assertForOpCount(name, Operation.INVALIDATE, 10);

      for (int i = 0; i < 10; i++) {
        Object key = i;
        EntryEvent ee = (EntryEvent) list.get(i);
        assertThat(ee.getKey()).isEqualTo(key);
        assertThat("old" + i).isEqualTo(ee.getOldValue());
        assertThat("callbackArg" + i).isEqualTo(ee.getCallbackArgument());
        assertThat(ee.isOriginRemote()).isTrue();
      }
    });

    vm2.invoke("Validate original and destroy", () -> {
      Region<Object, Object> region = getRootRegion().getSubregion(name);
      for (int i = 0; i < 10; i++) {
        Object key = i;
        assertThat(region.getEntry(key).getValue()).isEqualTo("new" + i);
        region.destroy(key, "destroyCB" + i);
        assertThat(region.getEntry(key)).isNull();
      }
    });

    vm1.invoke("Verify destroys", () -> {
      Region<Object, Object> region = getRootRegion().getSubregion(name);
      CertifiableTestCacheListener<Object, Object> ctl =
          (CertifiableTestCacheListener<Object, Object>) region.getAttributes()
              .getCacheListeners()[0];

      for (int i = 0; i < 10; i++) {
        Object key = i;
        ctl.waitForDestroyed(key);
        Region.Entry entry = region.getEntry(key);
        assertThat(entry).isNull();
      }

      List<CacheEvent<Object, Object>> list = assertForOpCount(name, Operation.DESTROY, 10);

      for (int i = 0; i < 10; i++) {
        Object key = i;
        EntryEvent ee = (EntryEvent) list.get(i);
        assertThat(ee.getKey()).isEqualTo(key);
        assertThat(ee.getOldValue()).isNull();
        assertThat("destroyCB" + i).isEqualTo(ee.getCallbackArgument());
        assertThat(ee.isOriginRemote()).isTrue();
      }
    });

    vm2.invoke("recreate", () -> {
      Region<Object, Object> region = getRootRegion().getSubregion(name);
      for (int i = 0; i < 10; i++) {
        Object key = i;
        region.create(key, "recreate" + i, "recreateCB" + i);
      }
    });

    vm1.invoke("Verify Local Load Creates", () -> {
      Region<Object, Object> region = getRootRegion().getSubregion(name);

      await().untilAsserted(() -> {
        for (int i = 0; i < 10; i++) {
          Object key = i;
          assertThat(region.containsKeyOnServer(key)).isTrue();
        }
      });

      for (int i = 0; i < 10; i++) {
        Object key = i;
        region.get(key, "recreateCB");
      }

      List<CacheEvent<Object, Object>> list =
          assertForOpCount(name, Operation.LOCAL_LOAD_CREATE, 10);

      for (int i = 0; i < 10; i++) {
        Object key = i;
        EntryEvent ee = (EntryEvent) list.get(i);
        assertThat(ee.getKey()).isEqualTo(key);
        assertThat(ee.getOldValue()).isNull();
        assertThat(ee.getNewValue()).isEqualTo("recreate" + i);
        assertThat(ee.isOriginRemote()).isFalse();
      }
    });

    vm1.invoke("Close Pool", () -> {
      Region<Object, Object> region = getRootRegion().getSubregion(name);
      region.localDestroyRegion();
    });
    vm2.invoke("Close Pool", () -> {
      Region<Object, Object> region = getRootRegion().getSubregion(name);
      region.localDestroyRegion();
    });
  }
Tests that invalidates and destroys are propagated to {@link Pool}s.

@since GemFire 3.5
geode-core/src/distributedTest/java/org/apache/geode/cache/ConnectionPoolDUnitTest.java