private void doTestRegisterInterestRemovesOldEntry(final String regionName, final boolean usePR)
      throws Exception {
    VM vm1 = Host.getHost(0).getVM(1);
    VM vm2 = Host.getHost(0).getVM(2);

    // here are the keys that will be used to validate behavior. Keys must be
    // colocated if using both a partitioned region in the server and transactions
    // in the client. All of these keys hash to bucket 0 in a two-bucket PR
    // except Object11 and IDoNotExist1
    final String key10 = "Object10";
    final String interestPattern = "Object.*";

    SerializableCallableIF createServer = getCreateServerCallable(regionName, usePR);
    int serverPort = (Integer) vm1.invoke(createServer);
    vm2.invoke(createServer);
    vm1.invoke(new SerializableRunnable("populate server") {
      @Override
      public void run() {
        Region myRegion = getCache().getRegion(regionName);
        for (int i = 1; i <= 20; i++) {
          myRegion.put("Object" + i, "Value" + i);
        }
      }
    });
    org.apache.geode.test.dunit.LogWriterUtils.getLogWriter().info("creating client cache");
    ClientCache c = new ClientCacheFactory().addPoolServer("localhost", serverPort)
        .set(LOG_LEVEL, LogWriterUtils.getDUnitLogLevel()).setPoolSubscriptionEnabled(true)
        .create();

    Region myRegion =
        c.createClientRegionFactory(ClientRegionShortcut.CACHING_PROXY).create(regionName);

    myRegion.registerInterestRegex(interestPattern);

    // make sure key1 is in the client because we're going to mess with it
    assertNotNull(myRegion.get(key10));

    // remove the entry for key1 on the servers and then simulate interest recovery
    // to show that the entry for key1 is no longer there in the client when recovery
    // finishes
    SerializableRunnable destroyKey10 =
        new SerializableRunnable("locally destroy " + key10 + " in the servers") {
          @Override
          public void run() {
            Region myRegion = getCache().getRegion(regionName);
            EntryEventImpl event = ((LocalRegion) myRegion).generateEvictDestroyEvent(key10);
            event.setOperation(Operation.LOCAL_DESTROY);
            if (usePR) {
              BucketRegion bucket = ((PartitionedRegion) myRegion).getBucketRegion(key10);
              if (bucket != null) {
                event.setRegion(bucket);
                org.apache.geode.test.dunit.LogWriterUtils.getLogWriter()
                    .info("performing local destroy in " + bucket + " ccEnabled="
                        + bucket.getConcurrencyChecksEnabled() + " rvv="
                        + bucket.getVersionVector());
                bucket.setConcurrencyChecksEnabled(false); // turn off cc so entry is removed
                bucket.mapDestroy(event, false, false, null);
                bucket.setConcurrencyChecksEnabled(true);
              }
            } else {
              ((LocalRegion) myRegion).setConcurrencyChecksEnabled(false); // turn off cc so entry
                                                                           // is
              // removed
              ((LocalRegion) myRegion).mapDestroy(event, false, false, null);
              ((LocalRegion) myRegion).setConcurrencyChecksEnabled(true);
            }
          }
        };

    vm1.invoke(destroyKey10);
    vm2.invoke(destroyKey10);

    myRegion.getCache().getLogger().info("clearing keys of interest");
    ((LocalRegion) myRegion).clearKeysOfInterest(interestPattern, InterestType.REGULAR_EXPRESSION,
        InterestResultPolicy.KEYS_VALUES);
    myRegion.getCache().getLogger().info("done clearing keys of interest");

    assertTrue("expected region to be empty but it has " + myRegion.size() + " entries",
        myRegion.size() == 0);

    RegionEntry entry;
    entry = ((LocalRegion) myRegion).getRegionEntry(key10);
    assertNull(entry); // it should have been removed

    // now register interest. At the end, finishRegisterInterest should clear
    // out the entry for key1 because it was stored in image-state as a
    // destroyed RI entry in clearKeysOfInterest
    myRegion.registerInterestRegex(interestPattern);

    entry = ((LocalRegion) myRegion).getRegionEntry(key10);
    assertNull(entry); // it should not be there
  }
Similar to bug #43407 but not reported in a ticket, we want a client that does a get() on a
destroyed entry to end up with a tombstone for that entry. This was already the case but there
were no unit tests covering this for different server configurations and with/without
transactions.
geode-core/src/distributedTest/java/org/apache/geode/internal/cache/ClientServerInvalidAndDestroyedEntryDUnitTest.java