@Test
  public void deprioritizeBootstrapReplicasTest() {
    assumeTrue(replicasStateEnabled && operationTrackerType.equals(SIMPLE_OP_TRACKER));
    initialize();
    Properties props = new Properties();
    props.setProperty(RouterConfig.ROUTER_GET_SUCCESS_TARGET, "1");
    props.setProperty(RouterConfig.ROUTER_GET_REQUEST_PARALLELISM, "3");
    props.setProperty(RouterConfig.ROUTER_GET_OPERATION_DEPRIORITIZE_BOOTSTRAP_REPLICAS, "true");
    originatingDcName = localDcName;

    // Case 1, set first replica to bootstrap
    // First replica is the local replica
    ReplicaId firstLocalReplica = mockPartition.replicaIds.get(0);
    assertEquals(localDcName, firstLocalReplica.getDataNodeId().getDatacenterName());
    mockPartition.setReplicaState(firstLocalReplica, ReplicaState.BOOTSTRAP);
    ReplicaId secondLocalReplica = mockPartition.replicaIds.get(4);
    ReplicaId thirdLocalReplica = mockPartition.replicaIds.get(8);

    SimpleOperationTracker ot =
        (SimpleOperationTracker) getOperationTracker(props, true, 3, RouterOperation.GetBlobOperation, true, true,
            false);
    assertEquals("Mismatch in replica count in the pool", 12, ot.getReplicaPoolSize());

    Iterator<ReplicaId> iterator = ot.getReplicaIterator();
    List<ReplicaId> orderedReplicas = new ArrayList<>();
    while (iterator.hasNext()) {
      orderedReplicas.add(iterator.next());
    }
    assertTrue(orderedReplicas.subList(0, 2).contains(secondLocalReplica));
    assertTrue(orderedReplicas.subList(0, 2).contains(thirdLocalReplica));
    assertEquals(firstLocalReplica, orderedReplicas.get(2));

    // Case 2, set second replica to bootstrap
    // Put it back to STANDBY
    mockPartition.setReplicaState(firstLocalReplica, ReplicaState.STANDBY);
    mockPartition.setReplicaState(secondLocalReplica, ReplicaState.BOOTSTRAP);

    ot = (SimpleOperationTracker) getOperationTracker(props, true, 3, RouterOperation.GetBlobOperation, true, true,
        false);
    assertEquals("Mismatch in replica count in the pool", 12, ot.getReplicaPoolSize());

    iterator = ot.getReplicaIterator();
    orderedReplicas = new ArrayList<>();
    while (iterator.hasNext()) {
      orderedReplicas.add(iterator.next());
    }
    assertTrue(orderedReplicas.subList(0, 2).contains(firstLocalReplica));
    assertTrue(orderedReplicas.subList(0, 2).contains(thirdLocalReplica));
    assertEquals(secondLocalReplica, orderedReplicas.get(2));

    // Case 3, first 2 replicas are bootstrap
    mockPartition.setReplicaState(firstLocalReplica, ReplicaState.BOOTSTRAP);
    mockPartition.setReplicaState(secondLocalReplica, ReplicaState.BOOTSTRAP);
    ot = (SimpleOperationTracker) getOperationTracker(props, true, 3, RouterOperation.GetBlobOperation, true, true,
        false);
    assertEquals("Mismatch in replica count in the pool", 12, ot.getReplicaPoolSize());

    iterator = ot.getReplicaIterator();
    orderedReplicas = new ArrayList<>();
    while (iterator.hasNext()) {
      orderedReplicas.add(iterator.next());
    }
    assertEquals(thirdLocalReplica, orderedReplicas.get(0));
    assertTrue(orderedReplicas.subList(1, 3).contains(firstLocalReplica));
    assertTrue(orderedReplicas.subList(1, 3).contains(secondLocalReplica));

    // Case 4. first one is offline, second one is bootstrap, third one is standby
    mockPartition.setReplicaState(firstLocalReplica, ReplicaState.OFFLINE);
    mockPartition.setReplicaState(secondLocalReplica, ReplicaState.BOOTSTRAP);
    ot = (SimpleOperationTracker) getOperationTracker(props, true, 3, RouterOperation.GetBlobOperation, true, true,
        false);
    assertEquals("Mismatch in replica count in the pool", 12, ot.getReplicaPoolSize());

    iterator = ot.getReplicaIterator();
    orderedReplicas = new ArrayList<>();
    while (iterator.hasNext()) {
      orderedReplicas.add(iterator.next());
    }
    assertEquals(thirdLocalReplica, orderedReplicas.get(0));
    assertEquals(secondLocalReplica, orderedReplicas.get(1));
  }
Test cases where some replicas have changed their state in the middle of constructing operation tracker. The code
should be able to get correct number of replicas even with concurrent state transition. The most common case is
replica changes from OFFLINE to BOOTSTRAP/STANDBY while the replica pool is being populated in the tracker.
ambry-router/src/test/java/com/github/ambry/router/OperationTrackerTest.java