@Test
  public void testConnectionAffinity() throws Exception {
    Host host = Host.getHost(0);
    VM server1 = host.getVM(0);
    VM server2 = host.getVM(1);
    VM client = host.getVM(2);

    IgnoredException.addIgnoredException("java.net.SocketException");

    final int port1 = createRegionsAndStartServer(server1, true);
    final int port2 = createRegionsAndStartServer(server2, false);


    SerializableCallable hostedSize = new SerializableCallable<Object>() {
      @Override
      public Object call() {
        TXManagerImpl mgr = getGemfireCache().getTxManager();
        return mgr.hostedTransactionsInProgressForTest();
      }
    };

    int txcount = (Integer) server1.invoke(hostedSize) + (Integer) server2.invoke(hostedSize);
    assertTrue("expected count to be 0" + txcount, txcount == 0);



    final TXId txid = (TXId) client.invoke(new SerializableCallable<Object>() {
      @Override
      public Object call() {
        ClientCacheFactory ccf = new ClientCacheFactory();
        ccf.addPoolServer("localhost"/* getServerHostName(Host.getHost(0)) */, port1);
        ccf.addPoolServer("localhost", port2);
        ccf.setPoolLoadConditioningInterval(1);
        ccf.setPoolSubscriptionEnabled(false);
        ccf.set(LOG_LEVEL, getDUnitLogLevel());
        ClientCache cCache = getClientCache(ccf);
        ClientRegionFactory<CustId, Customer> custrf =
            cCache.createClientRegionFactory(ClientRegionShortcut.PROXY);
        ClientRegionFactory<Integer, String> refrf =
            cCache.createClientRegionFactory(ClientRegionShortcut.PROXY);
        Region<Integer, String> r = refrf.create(D_REFERENCE);
        Region<CustId, Customer> pr = custrf.create(CUSTOMER);
        // Region<Integer, String> order = refrf.create(ORDER);

        TXManagerImpl mgr = getGemfireCache().getTxManager();
        mgr.begin();
        int i = 0;
        for (int j = 0; j < 10; j++) {
          CustId custId = new CustId(i);
          Customer cust = new Customer("name" + i, "address" + i);
          getGemfireCache().getLogger().info("SWAP:putting:" + custId);
          pr.put(custId, cust);
          r.put(i, "value" + i);
        }
        return mgr.suspend();
      }
    });

    SerializableCallable activeTx = new SerializableCallable<Object>() {
      @Override
      public Object call() {
        TXManagerImpl mgr = getGemfireCache().getTxManager();
        TXStateProxy tx = mgr.getHostedTXState(txid);
        mgr.getCache().getLogger().info("SWAP:activeTx:" + tx);
        // rather than returning strings representing objects
        // return different ints to represent different objects
        if (tx != null) {
          TXStateInterface realtx = ((TXStateProxyImpl) tx).getRealDeal(null, null);
          if (realtx instanceof TXState) {
            return 11;
          }
        }
        return 1;
      }
    };



    int myCount = (Integer) server1.invoke(activeTx) + (Integer) server2.invoke(activeTx);
    assertTrue("expected count to be 11 or 12 but was " + myCount, myCount >= 11 && myCount <= 12);

    client.invoke(new SerializableCallable<Object>() {
      @Override
      public Object call() {
        TXManagerImpl mgr = getGemfireCache().getTxManager();
        mgr.resume(txid);
        mgr.commit();
        return null;
      }
    });
  }
there is one txState and zero or more txProxyStates
geode-core/src/distributedTest/java/org/apache/geode/internal/cache/ClientServerTransactionDUnitTest.java