@Test
  public void testStats() throws CacheException {
    final int SLEEP_MS = 250;
    // final int OP_TIME = 0; // ns // changed form 10 to 0 because on fater platforms
    // and low resolution clocks this test will fail.
    final CachePerfStats stats = cache.getCachePerfStats();

    class statsValidator {
      private long txSuccessLifeTime;
      private long txFailedLifeTime;
      private long txRollbackLifeTime;
      private long txCommits;
      private long txFailures;
      private long txRollbacks;
      private long txCommitTime;
      private long txFailureTime;
      private long txRollbackTime;
      private long txCommitChanges;
      private long txFailureChanges;
      private long txRollbackChanges;

      private final CachePerfStats stats;

      private statsValidator(CachePerfStats stats) {
        this.stats = stats;
      }

      private void reset() {
        txSuccessLifeTime = stats.getTxSuccessLifeTime();
        txFailedLifeTime = stats.getTxFailedLifeTime();
        txRollbackLifeTime = stats.getTxRollbackLifeTime();
        txCommits = stats.getTxCommits();
        txFailures = stats.getTxFailures();
        txRollbacks = stats.getTxRollbacks();
        txCommitTime = stats.getTxCommitTime();
        txFailureTime = stats.getTxFailureTime();
        txRollbackTime = stats.getTxRollbackTime();
        txCommitChanges = stats.getTxCommitChanges();
        txFailureChanges = stats.getTxFailureChanges();
        txRollbackChanges = stats.getTxRollbackChanges();
      }

      private void setTxSuccessLifeTime(long txSuccessLifeTime) {
        this.txSuccessLifeTime = txSuccessLifeTime;
      }

      private void setTxFailedLifeTime(long txFailedLifeTime) {
        this.txFailedLifeTime = txFailedLifeTime;
      }

      private void setTxRollbackLifeTime(long txRollbackLifeTime) {
        this.txRollbackLifeTime = txRollbackLifeTime;
      }

      private void setTxCommits(long txCommits) {
        this.txCommits = txCommits;
      }

      private void setTxFailures(long txFailures) {
        this.txFailures = txFailures;
      }

      private void setTxRollbacks(long txRollbacks) {
        this.txRollbacks = txRollbacks;
      }

      private void setTxCommitTime(long txCommitTime) {
        this.txCommitTime = txCommitTime;
      }

      private void setTxFailureTime(long txFailureTime) {
        this.txFailureTime = txFailureTime;
      }

      private void setTxRollbackTime(long txRollbackTime) {
        this.txRollbackTime = txRollbackTime;
      }

      private void setTxCommitChanges(long txCommitChanges) {
        this.txCommitChanges = txCommitChanges;
      }

      private void setTxFailureChanges(long txFailureChanges) {
        this.txFailureChanges = txFailureChanges;
      }

      private void setTxRollbackChanges(long txRollbackChanges) {
        this.txRollbackChanges = txRollbackChanges;
      }

      private void assertValid() {
        assertEquals(txRollbacks, stats.getTxRollbacks());
        assertEquals(txRollbackChanges, stats.getTxRollbackChanges());
        if (Boolean
            .getBoolean(GeodeGlossary.GEMFIRE_PREFIX + "cache.enable-time-statistics")) {
          assertTrue(txRollbackTime <= stats.getTxRollbackTime());
          // assertTrue(this.txRollbackLifeTime+((SLEEP_MS-10)*1000000) <=
          // this.stats.getTxRollbackLifeTime());
          assertTrue(
              "RollbackLifeTime " + txRollbackLifeTime + " is not <= "
                  + stats.getTxRollbackLifeTime(),
              txRollbackLifeTime <= stats.getTxRollbackLifeTime());
          assertTrue(txCommitTime <= stats.getTxCommitTime());
          assertTrue(txSuccessLifeTime <= stats.getTxSuccessLifeTime());
          assertTrue(txFailureTime <= stats.getTxFailureTime());
          assertTrue(
              "FailedLifeTime " + txFailedLifeTime + " is not <= "
                  + stats.getTxFailedLifeTime(),
              txFailedLifeTime <= stats.getTxFailedLifeTime());
        }

        assertEquals(txCommits, stats.getTxCommits());
        assertEquals(txCommitChanges, stats.getTxCommitChanges());

        assertEquals(txFailures, stats.getTxFailures());
        assertEquals(txFailureChanges, stats.getTxFailureChanges());
      }
    }

    statsValidator statsVal = new statsValidator(stats);
    // Zero and non-zero rollback stats test
    int i;
    long testRollbackLifeTime = 0, testTotalTx = 0;
    for (i = 0; i < 2; ++i) {
      statsVal.reset();
      statsVal.setTxRollbacks(stats.getTxRollbacks() + 1);
      statsVal.setTxRollbackLifeTime(stats.getTxRollbackLifeTime() + ((SLEEP_MS - 20) * 1000000));
      final long beforeBegin = NanoTimer.getTime();
      txMgr.begin();
      final long afterBegin = NanoTimer.getTime();
      pause(SLEEP_MS);
      if (i > 0) {
        statsVal.setTxRollbackChanges(stats.getTxRollbackChanges() + 2);
        region.put("stats1", "stats rollback1");
        region.put("stats2", "stats rollback2");
      }
      statsVal.setTxRollbackTime(stats.getTxRollbackTime());
      final long beforeRollback = NanoTimer.getTime();
      txMgr.rollback();
      final long afterRollback = NanoTimer.getTime();
      final long statsRollbackLifeTime = stats.getTxRollbackLifeTime();
      testRollbackLifeTime += beforeRollback - afterBegin;
      // bruce - time based stats are disabled by default
      String p = (String) cache.getDistributedSystem().getProperties()
          .get(GeodeGlossary.GEMFIRE_PREFIX + "enable-time-statistics");
      if (p != null && Boolean.getBoolean(p)) {
        assertTrue("Local RollbackLifeTime assertion:  " + testRollbackLifeTime + " is not <= "
            + statsRollbackLifeTime, testRollbackLifeTime <= statsRollbackLifeTime);
      }
      testTotalTx += afterRollback - beforeBegin;
      final long totalTXMinusRollback = testTotalTx - stats.getTxRollbackTime();
      if (Boolean.getBoolean(GeodeGlossary.GEMFIRE_PREFIX + "cache.enable-time-statistics")) {
        assertTrue("Total Tx Minus Rollback assertion:  " + totalTXMinusRollback + " is not >= "
            + statsRollbackLifeTime, totalTXMinusRollback >= statsRollbackLifeTime);
      }
      statsVal.assertValid();
    }

    // Zero and non-zero commit stats test
    for (i = 0; i < 2; ++i) {
      statsVal.reset();
      statsVal.setTxCommits(stats.getTxCommits() + 1);
      statsVal.setTxSuccessLifeTime(stats.getTxSuccessLifeTime() + ((SLEEP_MS - 10) * 1000000));
      txMgr.begin();
      pause(SLEEP_MS);
      if (i > 0) {
        statsVal.setTxCommitChanges(stats.getTxCommitChanges() + 2);
        region.put("stats1", "commit1");
        region.put("stats2", "commit2");
      }
      try {
        statsVal.setTxCommitTime(stats.getTxCommitTime());
        txMgr.commit();
      } catch (CommitConflictException ex) {
        fail("unexpected " + ex);
      }
      statsVal.assertValid();
    }

    // Non-zero failed commit stats
    TXManagerImpl txMgrImpl = (TXManagerImpl) txMgr;
    statsVal.reset();
    statsVal.setTxFailures(stats.getTxFailures() + 1);
    statsVal.setTxFailureChanges(stats.getTxFailureChanges() + 2);
    statsVal.setTxFailedLifeTime(stats.getTxFailedLifeTime() + ((SLEEP_MS - 20) * 1000000));
    region.put("stats3", "stats fail3");
    txMgr.begin();
    region.put("stats1", "stats fail1");
    region.put("stats2", "stats fail2");
    try {
      region.create("stats3", "try stats3");
      fail("expected EntryExistsException");
    } catch (EntryExistsException ignored) {
    }
    // begin other tx simulation
    TXStateProxy tx = txMgrImpl.pauseTransaction();
    region.put("stats1", "stats success1");
    region.put("stats2", "stats success2");
    txMgrImpl.unpauseTransaction(tx);
    // end other tx simulation
    pause(SLEEP_MS);
    try {
      statsVal.setTxFailureTime(stats.getTxFailureTime());
      txMgr.commit();
      fail("expected CommitConflictException");
    } catch (CommitConflictException ex) {
      // expected failure
    }
    statsVal.assertValid();
  }
Test to make sure CacheListener callbacks are called in place with the CacheEvents properly
constructed
geode-core/src/integrationTest/java/org/apache/geode/TXJUnitTest.java