private void doBuildGetBlobOptionsTest(String rangeHeader, ByteRange expectedRange,
      boolean shouldSucceedWithoutSubResource, boolean shouldSucceedWithNonSegmentSubResource,
      boolean shouldSucceedWithSegment) throws RestServiceException {
    for (String resolveRangeOnEmptyBlobHeader : Arrays.asList(null, "true", "false")) {
      Map<String, Object> args = new HashMap<>();
      if (rangeHeader != null) {
        args.put(RestUtils.Headers.RANGE, rangeHeader);
      }
      if (resolveRangeOnEmptyBlobHeader != null) {
        args.put(RestUtils.Headers.RESOLVE_RANGE_ON_EMPTY_BLOB, resolveRangeOnEmptyBlobHeader);
      }
      boolean expectedResolveRangeOnEmptyBlob = "true".equals(resolveRangeOnEmptyBlobHeader);
      doBuildGetBlobOptionsTestForSubResource(args, null, expectedRange, GetBlobOptions.OperationType.All,
          expectedResolveRangeOnEmptyBlob, shouldSucceedWithoutSubResource);
      for (RestUtils.SubResource subResource : RestUtils.SubResource.values()) {
        if (subResource.equals(RestUtils.SubResource.Segment)) {
          doBuildGetBlobOptionsTestForSubResource(args, subResource, expectedRange, OperationType.All,
              expectedResolveRangeOnEmptyBlob, shouldSucceedWithSegment);
        } else if (subResource.equals(RestUtils.SubResource.BlobChunkIds)) {
          doBuildGetBlobOptionsTestForSubResource(args, subResource, expectedRange, OperationType.BlobChunkIds,
              expectedResolveRangeOnEmptyBlob, shouldSucceedWithNonSegmentSubResource);
        } else {
          doBuildGetBlobOptionsTestForSubResource(args, subResource, expectedRange,
              GetBlobOptions.OperationType.BlobInfo, expectedResolveRangeOnEmptyBlob,
              shouldSucceedWithNonSegmentSubResource);
        }
      }
    }
  }
Test that {@link RestUtils#buildGetBlobOptions(Map, RestUtils.SubResource, GetOption, int)} works correctly for a given
range with and without a specified sub-resource.
@param rangeHeader the Range header value to add to the {@code args} map.
@param expectedRange the {@link ByteRange} expected to be parsed if the call should succeed, or {@code null} if no
                     range is expected.
@param shouldSucceedWithoutSubResource {@code true} if the call should succeed with no specified sub-resource.
@param shouldSucceedWithNonSegmentSubResource {@code true} if the call should succeed with a specified non-Segment sub-resource.
@param shouldSucceedWithSegment {@code true} if the call should succeed with a specified Segment sub-resource
                                            (used if different than shouldSucceedWithSubResource).
@throws RestServiceException
ambry-api/src/test/java/com/github/ambry/rest/RestUtilsTest.java