@Test
  public void tombstoneAndGCShouldNotAffectTheEntryCount() {
    MemberVM locator = clusterStartupRule.startLocatorVM(0);
    int locatorPort = locator.getPort();
    MemberVM server0 =
        clusterStartupRule.startServerVM(1, s -> s.withConnectionToLocator(locatorPort));
    MemberVM server1 =
        clusterStartupRule.startServerVM(2, s -> s.withConnectionToLocator(locatorPort));
    MemberVM server2 =
        clusterStartupRule.startServerVM(3, s -> s.withConnectionToLocator(locatorPort));
    server0.invoke(() -> createPartitionedRegionWithRedundantCopies(regionName));
    server1.invoke(() -> createPartitionedRegionWithRedundantCopies(regionName));

    server0.invoke(() -> putDataInRegion(regionName));

    server0.invoke(() -> validateEntryCount(regionName, 4));
    server1.invoke(() -> validateEntryCount(regionName, 4));

    // Do a destroy
    server0.invoke(() -> {
      Cache cache = ClusterStartupRule.getCache();
      Region<Integer, Integer> region = cache.getRegion(regionName);
      region.destroy(0);
    });

    // We expect the tombstone won't be recorded as part of the entry count
    server0.invoke(() -> validateEntryCount(regionName, 3));
    server1.invoke(() -> validateEntryCount(regionName, 3));

    // Destroy and modify a tombstone
    server0.invoke(() -> {
      Cache cache = ClusterStartupRule.getCache();
      Region<Integer, Integer> region = cache.getRegion(regionName);
      region.destroy(113);
      region.put(113, 113);
    });

    server0.invoke(() -> validateEntryCount(regionName, 3));
    server1.invoke(() -> validateEntryCount(regionName, 3));

    // After GII (which might include the tombstone), a new members should still see only 2 live
    // entries.
    server2.invoke(() -> createPartitionedRegionWithRedundantCopies(regionName));

    // Wait for redundancy to be restored. Once it is the entry count should be 2
    server2.invoke(() -> {
      Cache cache = ClusterStartupRule.getCache();
      PartitionedRegion region = (PartitionedRegion) cache.getRegion(regionName);
      PartitionedRegionStats prStats = region.getPrStats();
      await()
          .untilAsserted(() -> assertThat(prStats.getLowRedundancyBucketCount()).isEqualTo(0));
    });

    server2.invoke(() -> validateEntryCount(regionName, 3));

    // A tombstone GC shouldn't affect the count.
    server0.invoke(() -> {
      InternalCache cache = ClusterStartupRule.getCache();
      TombstoneService tombstoneService = cache.getTombstoneService();
      tombstoneService.forceBatchExpirationForTests(1);
    });

    server0.invoke(() -> validateEntryCount(regionName, 3));
    server1.invoke(() -> validateEntryCount(regionName, 3));
    server2.invoke(() -> validateEntryCount(regionName, 3));
  }
Test to make sure the datastore entry count is accurate.
Region entry stats are validated before and after entry destroy.
Ensure that tombstones and tombstone GC are not affecting the region
entry count.
geode-core/src/distributedTest/java/org/apache/geode/internal/cache/PartitionedRegionStatsDistributedTest.java