@Test
  public void testPartialKeyInPRSingleHopWithRedundancy() throws Exception {
    // set <true, false> means <PR=true, notifyBySubscription=false> to test local-invalidates
    int serverPort1 = server1.invoke(() -> new ServerBuilder()
        .redundantCopies(1)
        .regionShortcut(PARTITION_PERSISTENT)
        .create());
    int serverPort2 = server2.invoke(() -> new ServerBuilder()
        .redundantCopies(1)
        .regionShortcut(PARTITION_PERSISTENT)
        .create());

    client1.invoke(() -> new ClientBuilder()
        .serverPorts(serverPort1, serverPort2)
        .subscriptionAckInterval()
        .subscriptionEnabled(true)
        .subscriptionRedundancy()
        .create());
    client2.invoke(() -> new ClientBuilder()
        .serverPorts(serverPort1, serverPort2)
        .subscriptionAckInterval()
        .subscriptionEnabled(true)
        .subscriptionRedundancy()
        .create());

    // client2 add listener
    client2.invoke(() -> {
      Region<String, TickerData> region = getClientCache().getRegion(regionName);
      region.registerInterest("ALL_KEYS");
    });

    // do some putAll to get ClientMetaData for future putAll
    client1.invoke(() -> doPutAll(getClientCache().getRegion(regionName), "key-", ONE_HUNDRED));

    await().untilAsserted(() -> {
      assertThat(client1.invoke(() -> getClientCache().getRegion(regionName).size()))
          .isEqualTo(ONE_HUNDRED);
      assertThat(client2.invoke(() -> getClientCache().getRegion(regionName).size()))
          .isEqualTo(ONE_HUNDRED);
      assertThat(server1.invoke(() -> getCache().getRegion(regionName).size()))
          .isEqualTo(ONE_HUNDRED);
      assertThat(server2.invoke(() -> getCache().getRegion(regionName).size()))
          .isEqualTo(ONE_HUNDRED);
    });

    // server1 add slow listener
    server1.invoke(() -> {
      Region<String, TickerData> region = getCache().getRegion(regionName);
      region.getAttributesMutator().addCacheListener(new SlowCacheListener<>());
    });

    // server2 add slow listener
    server2.invoke(() -> {
      Region<String, TickerData> region = getCache().getRegion(regionName);
      region.getAttributesMutator()
          .addCacheListener(new SlowCountingCacheListener<>(new Action<>(Operation.CREATE,
              creates -> executorServiceRule.submit(() -> closeCacheConditionally(creates, 10)))));
    });

    // client1 add listener and putAll
    AsyncInvocation<Void> registerInterestAndPutAllInClient1 = client1.invokeAsync(() -> {
      Region<String, TickerData> region = getClientCache().getRegion(regionName);
      region.registerInterest("ALL_KEYS");

      // create keys
      doPutAll(region, keyPrefix, ONE_HUNDRED);
    });

    // server2 will closeCache after created 10 keys

    registerInterestAndPutAllInClient1.await();

    int sizeOnClient1 = client1.invoke(() -> getClientCache().getRegion(regionName).size());
    int sizeOnClient2 = client2.invoke(() -> getClientCache().getRegion(regionName).size());
    int sizeOnServer1 = server1.invoke(() -> getCache().getRegion(regionName).size());
    // putAll should succeed after retry
    assertThat(sizeOnClient1).isEqualTo(sizeOnServer1);
    assertThat(sizeOnClient2).isEqualTo(sizeOnServer1);

    // restart server2
    server2.invoke(() -> {
      new ServerBuilder()
          .redundantCopies(1)
          .regionShortcut(PARTITION_PERSISTENT)
          .create();
    });

    sizeOnServer1 = server1.invoke(() -> getCache().getRegion(regionName).size());
    int sizeOnServer2 = server2.invoke(() -> getCache().getRegion(regionName).size());
    assertThat(sizeOnServer1).isEqualTo(sizeOnClient2);
    assertThat(sizeOnServer2).isEqualTo(sizeOnClient2);

    // close a server to re-run the test
    server2.invoke(() -> getCache().close());

    // client1 does putAll again
    client1.invoke(
        () -> doPutAll(getClientCache().getRegion(regionName), keyPrefix + "again:", ONE_HUNDRED));

    int newSizeOnServer1 = server1.invoke(() -> getCache().getRegion(regionName).size());
    int newSizeOnClient1 = client1.invoke(() -> getClientCache().getRegion(regionName).size());
    int newSizeOnClient2 = client2.invoke(() -> getClientCache().getRegion(regionName).size());

    // putAll should succeed, all the numbers should match
    assertThat(newSizeOnClient1).isEqualTo(newSizeOnServer1);
    assertThat(newSizeOnClient2).isEqualTo(newSizeOnServer1);
  }
Set redundancy=1 to see if retry succeeded after PRE This is a singlehop putAll test.
geode-cq/src/distributedTest/java/org/apache/geode/internal/cache/PutAllClientServerDistributedTest.java