@Test
  public void regionIsUsableBeforeRedundancyRecovery() throws Exception {
    int redundancy = 1;
    int numBuckets = 20;

    vm0.invoke(() -> createPartitionedRegion(redundancy, -1, 113, true));
    vm1.invoke(() -> createPartitionedRegion(redundancy, -1, 113, true));
    vm2.invoke(() -> createPartitionedRegion(redundancy, -1, 113, true));

    vm0.invoke(() -> createData(0, numBuckets, "a"));

    Set<Integer> bucketsOnVM0 = vm0.invoke(this::getBucketList);
    Set<Integer> bucketsOnVM1 = vm1.invoke(this::getBucketList);
    Set<Integer> bucketsOnVM2 = vm2.invoke(this::getBucketList);

    vm0.invoke(() -> getCache().close());
    vm1.invoke(() -> getCache().close());
    vm2.invoke(() -> getCache().close());

    try {
      vm0.invoke(this::slowGII);
      vm1.invoke(this::slowGII);
      vm2.invoke(this::slowGII);

      AsyncInvocation<Void> createPartitionedRegionOnVM0 =
          vm0.invokeAsync(() -> createPartitionedRegionWithPersistence(redundancy));
      AsyncInvocation<Void> createPartitionedRegionOnVM1 =
          vm1.invokeAsync(() -> createPartitionedRegionWithPersistence(redundancy));
      AsyncInvocation<Void> createPartitionedRegionOnVM2 =
          vm2.invokeAsync(() -> createPartitionedRegionWithPersistence(redundancy));

      createPartitionedRegionOnVM0.await();
      createPartitionedRegionOnVM1.await();
      createPartitionedRegionOnVM2.await();

      // Make sure all of the primary are available.
      vm0.invoke(() -> {
        checkData(0, numBuckets, "a");
        createData(113, 113 + numBuckets, "b");
      });

      // But none of the secondaries
      Set<Integer> initialBucketsOnVM0 = vm0.invoke(this::getBucketList);
      Set<Integer> initialBucketsOnVM1 = vm1.invoke(this::getBucketList);
      Set<Integer> initialBucketsOnVM2 = vm2.invoke(this::getBucketList);

      assertThat(
          initialBucketsOnVM0.size() + initialBucketsOnVM1.size() + initialBucketsOnVM2.size())
              .as("vm0=" + initialBucketsOnVM0 + ",vm1=" + initialBucketsOnVM1 + "vm2="
                  + initialBucketsOnVM2)
              .isEqualTo(numBuckets);
    } finally {
      // Reset the slow GII flag, and wait for the redundant buckets to be recovered.
      AsyncInvocation<Void> resetSlowGiiOnVM0 = vm0.invokeAsync(this::resetSlowGII);
      AsyncInvocation<Void> resetSlowGiiOnVM1 = vm1.invokeAsync(this::resetSlowGII);
      AsyncInvocation<Void> resetSlowGiiOnVM2 = vm2.invokeAsync(this::resetSlowGII);

      resetSlowGiiOnVM0.await();
      resetSlowGiiOnVM1.await();
      resetSlowGiiOnVM2.await();
    }

    // Now we better have all of the buckets
    assertThat(vm0.invoke(this::getBucketList)).isEqualTo(bucketsOnVM0);
    assertThat(vm1.invoke(this::getBucketList)).isEqualTo(bucketsOnVM1);
    assertThat(vm2.invoke(this::getBucketList)).isEqualTo(bucketsOnVM2);

    // Make sure the members see the data recovered from disk in those secondary buckets
    vm0.invoke(() -> checkData(0, numBuckets, "a"));
    vm1.invoke(() -> checkData(0, numBuckets, "a"));

    // Make sure the members see the new updates in those secondary buckets
    vm0.invoke(() -> checkData(113, 113 + numBuckets, "b"));
    vm1.invoke(() -> checkData(113, 113 + numBuckets, "b"));
  }
A test to make sure that we allow the PR to be used after at least one copy of every bucket is
recovered, but before the secondaries are initialized.
geode-core/src/distributedTest/java/org/apache/geode/internal/cache/partitioned/PersistentPartitionedRegionDistributedTest.java