@Test
  public void testDurableClientReconnectTwoServers() throws InterruptedException {
    // Start server 1
    server1Port = server1VM.invoke(
        () -> createCacheServer(regionName, true));

    // on test flag for periodic ack
    server1VM
        .invoke(() -> setTestFlagToVerifyActForMarker(true));

    // Start server 2 using the same mcast port as server 1
    final int server2Port = server2VM
        .invoke(() -> createCacheServer(regionName, true));

    // Stop server 2
    server2VM.invoke((SerializableRunnableIF) CacheServerTestUtil::closeCache);

    // Start a durable client that is kept alive on the server when it stops
    // normally
    final String durableClientId = getName() + "_client";
    final int durableClientTimeout = 60; // keep the client alive for 60 seconds
    // final boolean durableClientKeepAlive = true; // keep the client alive when it stops normally
    durableClientVM.invoke(() -> createCacheClient(
        getClientPool(getServerHostName(), server1Port, server2Port, true),
        regionName, getClientDistributedSystemProperties(durableClientId, durableClientTimeout),
        true));

    // Send clientReady message
    sendClientReady(durableClientVM);

    registerInterest(durableClientVM, regionName, true, NONE);

    // Verify durable client on server 1
    server1VM.invoke("Verify durable client", new CacheSerializableRunnable() {
      @Override
      public void run2() throws CacheException {
        // Find the proxy
        checkNumberOfClientProxies(1);
        CacheClientProxy proxy = getClientProxy();
        assertThat(proxy).isNotNull();

        // Verify that it is durable and its properties are correct
        assertThat(proxy.isDurable()).isTrue();
        assertThat(durableClientId).isEqualTo(proxy.getDurableId());
        assertThat(durableClientTimeout).isEqualTo(proxy.getDurableTimeout());
        verifyReceivedMarkerAck();
      }
    });

    // VJR: wait for ack to go out
    pause(5000);

    // Stop the durable client
    durableClientVM.invoke(() -> CacheServerTestUtil.closeCache(true));

    // Verify durable client on server 1
    server1VM.invoke("Verify durable client", new CacheSerializableRunnable() {
      @Override
      public void run2() throws CacheException {
        // Find the proxy
        checkNumberOfClientProxies(1);
        CacheClientProxy proxy = getClientProxy();
        assertThat(proxy).isNotNull();
      }
    });

    // Re-start server2
    server2VM.invoke(() -> createCacheServer(regionName, true,
        server2Port));

    // Start normal publisher client
    publisherClientVM.invoke(() -> createCacheClient(getClientPool(getServerHostName(),
        server1Port, server2Port, false), regionName));

    // Publish some entries
    final int numberOfEntries = 10;
    publishEntries(publisherClientVM, 0, numberOfEntries);

    sleep(1000);

    // Verify the durable client's queue contains the entries
    server1VM.invoke("Verify durable client", new CacheSerializableRunnable() {
      @Override
      public void run2() throws CacheException {
        // Find the proxy
        CacheClientProxy proxy = getClientProxy();
        assertThat(proxy).isNotNull();

        // Verify the queue size
        assertThat(numberOfEntries).isEqualTo(proxy.getQueueSize());
      }
    });

    // Re-start the durable client that is kept alive on the server when it stops
    // normally
    durableClientVM.invoke(() -> createCacheClient(
        getClientPool(getServerHostName(), server1Port, server2Port, true),
        regionName, getClientDistributedSystemProperties(durableClientId, durableClientTimeout),
        true));

    // Send clientReady message
    sendClientReady(durableClientVM);

    // Verify durable client on server 1
    verifyDurableClientPresence(durableClientTimeout, durableClientId, server1VM, 1);

    // Verify durable client on server 2
    verifyDurableClientPresence(durableClientTimeout, durableClientId, server2VM, 1);

    // Verify the HA region names are the same on both servers
    String server1HARegionQueueName =
        server1VM.invoke(DurableClientTestBase::getHARegionQueueName);
    String server2HARegionQueueName =
        server2VM.invoke(DurableClientTestBase::getHARegionQueueName);
    assertThat(server1HARegionQueueName).isEqualTo(server2HARegionQueueName);

    // Verify the durable client received the updates
    checkListenerEvents(numberOfEntries, 1, -1, durableClientVM);

    // Stop the durable client
    durableClientVM.invoke((SerializableRunnableIF) CacheServerTestUtil::closeCache);

    // Stop the publisher client
    publisherClientVM.invoke((SerializableRunnableIF) CacheServerTestUtil::closeCache);

    // off test flag for periodic ack
    server1VM.invoke(() -> setTestFlagToVerifyActForMarker(false));

    // Stop server 1
    server1VM.invoke((SerializableRunnableIF) CacheServerTestUtil::closeCache);

    // Stop server 2
    server2VM.invoke((SerializableRunnableIF) CacheServerTestUtil::closeCache);
  }
Tests whether a durable client reconnects properly to two servers.
geode-cq/src/distributedTest/java/org/apache/geode/internal/cache/tier/sockets/DurableClientSimpleDUnitTest.java