@Test
  public void testTxRemove() {
    Host host = Host.getHost(0);
    VM acc = host.getVM(0);
    VM datastore = host.getVM(1);
    initAccessorAndDataStore(acc, datastore, 0);
    VM accessor = getVMForTransactions(acc, datastore);

    final CustId custId = new CustId(1);
    final TXId txId = (TXId) accessor.invoke(new SerializableCallable<Object>() {
      @Override
      public Object call() {
        Region<CustId, Customer> cust = getCache().getRegion(CUSTOMER);
        Region<CustId, Customer> ref = getCache().getRegion(D_REFERENCE);
        TXManagerImpl mgr = getCache().getTxManager();
        mgr.begin();
        Customer customer = new Customer("customer1", "address1");
        Customer fakeCust = new Customer("foo", "bar");
        assertThat(cust.remove(custId, fakeCust)).isFalse();
        assertThat(cust.remove(custId, customer)).isTrue();
        assertThat(ref.remove(custId, fakeCust)).isFalse();
        assertThat(ref.remove(custId, customer)).isTrue();
        TXStateProxy tx = mgr.pauseTransaction();
        assertThat(cust.get(custId)).isNotNull();
        assertThat(ref.get(custId)).isNotNull();
        mgr.unpauseTransaction(tx);
        return mgr.suspend();
      }
    });
    datastore.invoke(new SerializableCallable<Object>() {
      @Override
      public Object call() {
        TXManagerImpl mgr = getCache().getTxManager();
        assertThat(mgr.isHostedTxInProgress(txId)).isTrue();
        TXStateProxy tx = mgr.getHostedTXState(txId);
        assertThat(tx.getRegions().size()).isEqualTo(2);// 2 buckets for the two puts we
        // did in the accessor one dist. region, and one more bucket if Cust1 and Cust10 resolve to
        // different buckets
        for (InternalRegion r : tx.getRegions()) {
          assertThat(r instanceof DistributedRegion).isTrue();
          TXRegionState rs = tx.readRegion(r);
          for (Object key : rs.getEntryKeys()) {
            TXEntryState es = rs.readEntry(key);
            assertThat(es.getValue(key, r, false)).isNull();
            assertThat(es.isDirty()).as("key:" + key + " r:" + r.getFullPath()).isTrue();
          }
        }
        return null;
      }
    });
    accessor.invoke(new SerializableCallable<Object>() {
      @Override
      public Object call() {
        TXManagerImpl mgr = getCache().getTxManager();
        mgr.resume(txId);
        mgr.commit();
        Region<CustId, Customer> cust = getCache().getRegion(CUSTOMER);
        Region<CustId, Customer> rr = getCache().getRegion(D_REFERENCE);
        assertThat(cust.get(custId)).isNull();
        assertThat(rr.get(custId)).isNull();
        // check conflict
        mgr.begin();
        CustId conflictCust = new CustId(2);
        Customer customer = new Customer("customer2", "address2");
        getCache().getLogger().fine("SWAP:removeConflict");
        assertThat(cust.remove(conflictCust, customer)).isTrue();
        TXStateProxy tx = mgr.pauseTransaction();
        cust.put(conflictCust, new Customer("foo", "bar"));
        mgr.unpauseTransaction(tx);
        assertThatThrownBy(mgr::commit).isInstanceOf(CommitConflictException.class);
        return null;
      }
    });
  }
Make sure that getEntry returns null properly and values when it should
geode-core/src/distributedTest/java/org/apache/geode/internal/cache/RemoteTransactionDUnitTest.java