@Test
  public void testDRFunctionExecution() {
    Host host = Host.getHost(0);
    VM accessor = host.getVM(0);
    VM datastore1 = host.getVM(1);
    VM datastore2 = host.getVM(2);

    class CreateDR extends SerializableCallable {
      private final boolean isAccessor;

      public CreateDR(boolean isAccessor) {
        this.isAccessor = isAccessor;
      }

      @Override
      public Object call() {
        AttributesFactory af = new AttributesFactory();
        af.setDataPolicy(isAccessor ? DataPolicy.EMPTY : DataPolicy.REPLICATE);
        af.setScope(Scope.DISTRIBUTED_ACK);
        af.setConcurrencyChecksEnabled(getConcurrencyChecksEnabled());
        getCache().createRegion(CUSTOMER, af.create());
        if (isAccessor) {
          Region custRegion = getCache().getRegion(CUSTOMER);
          for (int i = 0; i < 5; i++) {
            CustId custId = new CustId(i);
            Customer customer = new Customer("customer" + i, "address" + i);
            custRegion.put(custId, customer);
          }
        }
        return null;
      }
    }

    datastore1.invoke(new CreateDR(false));
    datastore2.invoke(new CreateDR(false));
    accessor.invoke(new CreateDR(true));

    SerializableCallable registerFunction = new SerializableCallable<Object>() {
      @Override
      public Object call() {
        FunctionService.registerFunction(new TXFunction());
        return null;
      }
    };

    accessor.invoke(registerFunction);
    datastore1.invoke(registerFunction);
    datastore2.invoke(registerFunction);

    accessor.invoke(new SerializableCallable<Object>() {
      @Override
      public Object call() {
        Region custRegion = getCache().getRegion(CUSTOMER);
        TXManagerImpl mgr = getCache().getTXMgr();
        mgr.begin();
        FunctionService.onRegion(custRegion).execute(TXFunction.id).getResult();
        assertThat(mgr.getTXState()).isNotNull();
        TXStateProxy tx = mgr.pauseTransaction();
        assertThat(mgr.getTXState()).isNull();
        getCache().getLogger().fine("SWAP:callingget");
        assertThat(custRegion.get(expectedCustId))
            .as("expected null but was:" + custRegion.get(expectedCustId)).isNull();
        mgr.unpauseTransaction(tx);
        mgr.commit();
        assertThat(expectedCustomer).isEqualTo(custRegion.get(expectedCustId));
        return null;
      }
    });

    datastore1.invoke(new SerializableCallable<Object>() {
      @Override
      public Object call() {
        final Region custRegion = getCache().getRegion(CUSTOMER);
        TXManagerImpl mgr = getCache().getTXMgr();
        mgr.begin();
        FunctionService.onRegion(custRegion).execute(new FunctionAdapter() {
          @Override
          public String getId() {
            return "LocalDS";
          }

          @Override
          public void execute(FunctionContext context) {
            assertThat(getCache().getTxManager().getTXState()).isNotNull();
            custRegion.destroy(expectedCustId);
            context.getResultSender().lastResult(Boolean.TRUE);
          }
        }).getResult();
        TXStateProxy tx = mgr.pauseTransaction();
        assertThat(custRegion.get(expectedCustId)).isEqualTo(expectedCustomer);
        mgr.unpauseTransaction(tx);
        mgr.commit();
        assertThat(custRegion.get(expectedCustId)).isNull();
        return null;
      }
    });
  }
When we have narrowed down on a target node for a transaction, test that we throw an exception
if that node does not host primary for subsequent entries
geode-core/src/distributedTest/java/org/apache/geode/internal/cache/RemoteTransactionDUnitTest.java