@Test
  public void testDistributedStats() {
    final String name = getUniqueName();
    final Object key0 = 0;
    final Object key1 = 1;
    final Object key2 = 2;
    final Object key3 = 3;
    final Object value = "VALUE";
    final Object value1 = "VALUE1";
    final Object value2 = "VALUE2";
    final Object value3 = "VALUE3";
    final Object notPresentKey1 = "NOT_PRESENT_1";
    final Object notPresentKey2 = "NOT_PRESENT_2";
    final Object notPresentKey3 = "NOT_PRESENT_3";
    final Object notPresentKey4 = "NOT_PRESENT_4";

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

    SerializableRunnableIF create = () -> {
      AttributesFactory factory = new AttributesFactory();
      factory.setEarlyAck(false);
      factory.setStatisticsEnabled(true);
      createPartitionedRegion(name, factory.create());
    };

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

    vm0.invoke(() -> {
      Region region = getRootRegion(name);
      CacheStatistics stats = region.getStatistics();
      region.put(key0, value);
      region.put(key1, value1);

      assertTrue(stats.getLastModifiedTime() > lastModified);
      assertEquals(0, stats.getHitCount());
      assertEquals(0, stats.getMissCount());
    });

    vm1.invoke(() -> {
      Region region = getRootRegion(name);
      CacheStatistics stats = region.getStatistics();
      region.put(key2, value3);
      region.put(key3, value3);

      assertTrue(stats.getLastModifiedTime() > lastModified);
      assertEquals(0, stats.getHitCount());
      assertEquals(0, stats.getMissCount());
    });

    vm0.invoke(() -> {
      Region region = getRootRegion(name);
      CacheStatistics stats = region.getStatistics();
      lastAccessed = stats.getLastAccessedTime();
      lastModified = stats.getLastModifiedTime();

      Object result = region.get(key0);
      region.get(key1);
      region.get(key2);
      region.get(key3);
      region.get(notPresentKey1);
      region.get(notPresentKey2);
      region.get(notPresentKey3);
      region.get(notPresentKey4);

      assertEquals(value, result);
      assertEquals(2, stats.getMissCount());
      assertEquals(2, stats.getHitCount());
      assertTrue(stats.getLastAccessedTime() > lastAccessed);
    });

    vm0.invoke(() -> {
      Region region = getRootRegion(name);
      CacheStatistics stats = region.getStatistics();
      lastAccessed = stats.getLastAccessedTime();

      Object result = region.get(key0);
      region.get(key1);
      region.get(key2);
      region.get(key3);
      region.get(notPresentKey1);
      region.get(notPresentKey2);
      region.get(notPresentKey3);
      region.get(notPresentKey4);

      assertEquals(value, result);
      assertEquals(4, stats.getHitCount());
      assertEquals(4, stats.getMissCount());
      assertTrue(stats.getLastAccessedTime() > lastAccessed);
    });

    vm0.invoke(() -> {
      Region region = getRootRegion(name);
      CacheStatistics stats = region.getStatistics();
      long before = ((InternalRegion) region).cacheTimeMillis();
      region.put(key0, value);
      region.put(key1, value1);
      region.put(key2, value2);
      region.put(key3, value3);
      long after = ((InternalRegion) region).cacheTimeMillis();
      assertTrue(before <= stats.getLastModifiedTime());
      assertTrue(after >= stats.getLastModifiedTime());
    });

    vm1.invoke(() -> {
      Region region = getRootRegion(name);
      CacheStatistics stats = region.getStatistics();
      long before = ((InternalRegion) region).cacheTimeMillis();
      region.put(key0, value);
      region.put(key1, value1);
      region.put(key2, value2);
      region.put(key3, value3);
      long after = ((InternalRegion) region).cacheTimeMillis();
      assertTrue(before <= stats.getLastModifiedTime());
      assertTrue(after >= stats.getLastModifiedTime());
    });

    vm0.invoke(() -> {
      Region region = getRootRegion(name);
      CacheStatistics stats = region.getStatistics();
      lastAccessed = stats.getLastAccessedTime();
      lastModified = stats.getLastModifiedTime();
      region.invalidate(key0);
      region.invalidate(key1);
      assertEquals(lastAccessed, stats.getLastAccessedTime());
      assertEquals(lastModified, stats.getLastModifiedTime());
      assertEquals(4, stats.getHitCount());
      assertEquals(4, stats.getMissCount());
    });

    vm1.invoke(() -> {
      Region region = getRootRegion(name);
      CacheStatistics stats = region.getStatistics();
      lastAccessed = stats.getLastAccessedTime();
      lastModified = stats.getLastModifiedTime();
      region.invalidate(key2);
      region.invalidate(key3);

      assertEquals(lastAccessed, stats.getLastAccessedTime());
      assertEquals(lastModified, stats.getLastModifiedTime());
      assertEquals(4, stats.getHitCount());
      assertEquals(4, stats.getMissCount());
    });

    vm0.invoke(() -> {
      Region region = getRootRegion(name);
      CacheStatistics stats = region.getStatistics();
      lastModified = stats.getLastModifiedTime();
      region.destroy(key0);
      region.destroy(key1);

      assertEquals(lastModified, stats.getLastModifiedTime());
      assertEquals(4, stats.getHitCount());
      assertEquals(4, stats.getMissCount());
    });

    vm1.invoke(() -> {
      Region region = getRootRegion(name);
      CacheStatistics stats = region.getStatistics();
      lastModified = stats.getLastModifiedTime();
      region.destroy(key2);
      region.destroy(key3);

      assertEquals(lastModified, stats.getLastModifiedTime());
      assertEquals(4, stats.getHitCount());
      assertEquals(4, stats.getMissCount());
    });

  }
Tests that the {@link CacheStatistics#getHitCount hit count},
{@link CacheStatistics#getMissCount miss count},
{@linkplain CacheStatistics#getLastAccessedTime last access time}
and {@link CacheStatistics#getLastModifiedTime last modified time} are updated
properly for a partitioned region
with more than one server.
geode-core/src/distributedTest/java/org/apache/geode/cache30/CacheStatisticsPartitionedRegionDUnitTest.java