@Test
  public void testBucketImageProviderBouncesDuringBucketMove()
      throws InterruptedException, TimeoutException {
    getBlackboard().initBlackboard();

    // Setting up 3 servers to create the partitioned region on to avoid issues with
    // losing membership quorum. Alternatively we could disable network partition detection
    // when constructing the cache, but this solves the same problem.
    VM server1 = getVM(0);
    VM server2 = getVM(1);
    VM server3 = getVM(2);

    int redundantCopies = 0;
    String regionName = "region1";

    server1.invoke(() -> createPersistentPartitionedRegion(regionName, getUniqueName(),
        getDiskDirs(), redundantCopies));

    // Do puts before starting the second server so that we guarantee all buckets reside on the
    // first server. This way we ensure a rebalance should have some work to do.
    server1.invoke(() -> {
      doPuts(regionName);
    });

    // Recycling server 2 and 3 sets the "recreated" state on the partitioned buckets, which can
    // change the behavior during failed GII handling when receiving bucket images. See
    // AbstractDiskRegion.isRecreated.
    server2.invoke(() -> createPersistentPartitionedRegion(regionName, getUniqueName(),
        getDiskDirs(), redundantCopies));

    server3.invoke(() -> createPersistentPartitionedRegion(regionName, getUniqueName(),
        getDiskDirs(), redundantCopies));

    server2.invoke(() -> {
      getCache().close();
      createPersistentPartitionedRegion(regionName, getUniqueName(), getDiskDirs(),
          redundantCopies);
    });

    server3.invoke(() -> {
      getCache().close();
      createPersistentPartitionedRegion(regionName, getUniqueName(), getDiskDirs(),
          redundantCopies);
    });

    server1.invokeAsync(() -> {
      InternalResourceManager manager = getCache().getInternalResourceManager();

      // This will signal a bounce of the VM upon receving the request for any bucket GII for the
      // test partitioned region
      DistributionMessageObserver
          .setInstance(new SignalBounceOnRequestImageMessageObserver("_B__" + regionName + "_",
              getCache(), getBlackboard()));

      doRebalance(false, manager);
    });

    SignalBounceOnRequestImageMessageObserver.waitThenBounce(getBlackboard(), server1);

    server1.invoke(() -> {
      // Rebuild the cache and retry the rebalance. We expect it to succeed because the
      // SignalBounceOnRequestImageMessageObserver has been uninstalled.
      createPersistentPartitionedRegion(regionName, getUniqueName(), getDiskDirs(),
          redundantCopies);
      InternalResourceManager manager = getCache().getInternalResourceManager();
      RebalanceResults results = doRebalance(false, getCache().getInternalResourceManager());

      // The rebalance should have done some work since the buckets were imbalanced
      assertThat(results.getTotalBucketTransfersCompleted() > 0).isTrue();
    });
  }
If the bucket image provider is bounced while a bucket is moving during a rebalance,
we expect a subsequent rebalance will succeed after member restarts and cache is reconstructed.
geode-core/src/distributedTest/java/org/apache/geode/internal/cache/control/RebalanceOperationDistributedTest.java