private OperationTracker getOperationTracker(Properties props, boolean crossColoEnabled, int parallelism,
      RouterOperation routerOperation, boolean includeDownReplicas, boolean terminateOnNotFoundEnabled,
      boolean shouldShuffle) {
    props.setProperty(RouterConfig.ROUTER_HOSTNAME, "localhost");
    props.setProperty(RouterConfig.ROUTER_DATACENTER_NAME, localDcName);
    props.setProperty(RouterConfig.ROUTER_GET_CROSS_DC_ENABLED, Boolean.toString(crossColoEnabled));
    props.setProperty(RouterConfig.ROUTER_PUT_REQUEST_PARALLELISM, Integer.toString(parallelism));
    props.setProperty(RouterConfig.ROUTER_LATENCY_TOLERANCE_QUANTILE, Double.toString(QUANTILE));
    props.setProperty(RouterConfig.ROUTER_OPERATION_TRACKER_MAX_INFLIGHT_REQUESTS, Integer.toString(parallelism));
    props.setProperty(RouterConfig.ROUTER_OPERATION_TRACKER_TERMINATE_ON_NOT_FOUND_ENABLED,
        Boolean.toString(terminateOnNotFoundEnabled));
    props.setProperty(RouterConfig.ROUTER_GET_ELIGIBLE_REPLICAS_BY_STATE_ENABLED,
        Boolean.toString(replicasStateEnabled));
    props.setProperty(RouterConfig.ROUTER_PUT_USE_DYNAMIC_SUCCESS_TARGET, Boolean.toString(useDynamicTargetForPut));
    props.setProperty(RouterConfig.ROUTER_CROSS_COLO_REQUEST_TO_DC_WITH_MOST_REPLICAS,
        Boolean.toString(chooseDcWithMostReplicas));
    props.setProperty(RouterConfig.ROUTER_OPERATION_TRACKER_INCLUDE_DOWN_REPLICAS,
        Boolean.toString(includeDownReplicas));
    RouterConfig routerConfig = new RouterConfig(new VerifiableProperties(props));
    NonBlockingRouterMetrics routerMetrics = new NonBlockingRouterMetrics(mockClusterMap, routerConfig);
    OperationTracker tracker;
    switch (operationTrackerType) {
      case SIMPLE_OP_TRACKER:
        tracker = new SimpleOperationTracker(routerConfig, routerOperation, mockPartition, originatingDcName, true,
            routerMetrics);
        break;
      case ADAPTIVE_OP_TRACKER:
        // for now adaptive operation tracker only applies to GetOperation.
        if (!EnumSet.of(RouterOperation.GetBlobInfoOperation, RouterOperation.GetBlobOperation)
            .contains(routerOperation)) {
          throw new IllegalArgumentException("Adaptive tracker currently is not used for " + routerOperation);
        }
        tracker =
            new AdaptiveOperationTracker(routerConfig, routerMetrics, routerOperation, mockPartition, originatingDcName,
                time);
        break;
      default:
        throw new IllegalArgumentException("Unrecognized operation tracker type - " + operationTrackerType);
    }
    return tracker;
  }
Returns the right {@link OperationTracker} based on {@link #operationTrackerType}.
@param props {@link Properties} for {@link RouterConfig}.
@param crossColoEnabled {@code true} if cross colo needs to be enabled. {@code false} otherwise.
@param parallelism the number of parallel requests that can be in flight.
@param routerOperation the {@link RouterOperation} associate with this request.
@param includeDownReplicas whether to include down replicas in operation tracker.
@param terminateOnNotFoundEnabled whether to terminate the operation if we received not found responses.
@param shouldShuffle whether to shuffle replicas
@return the right {@link OperationTracker} based on {@link #operationTrackerType}.
ambry-router/src/test/java/com/github/ambry/router/OperationTrackerTest.java