private void doChunkUploadTest(int contentLength, boolean chunkUpload, String uploadSession, Integer maxUploadSize,
      long blobTtlSecs, ThrowingConsumer<ExecutionException> errorChecker, int callCount)
      throws Exception {
    JSONObject headers = new JSONObject();
    FrontendRestRequestServiceTest.setAmbryHeadersForPut(headers, blobTtlSecs, !REF_CONTAINER.isCacheable(), SERVICE_ID,
        CONTENT_TYPE, OWNER_ID, REF_ACCOUNT.getName(), REF_CONTAINER.getName(), null);
    if (chunkUpload) {
      headers.put(RestUtils.Headers.CHUNK_UPLOAD, true);
    }
    if (uploadSession != null) {
      headers.put(RestUtils.Headers.SESSION, uploadSession);
    }
    if (maxUploadSize != null) {
      headers.put(RestUtils.Headers.MAX_UPLOAD_SIZE, maxUploadSize);
    }
    if (reservedMetadataId != null) {
      headers.put(RestUtils.Headers.RESERVED_METADATA_ID, reservedMetadataId);
    }
    byte[] content = TestUtils.getRandomBytes(contentLength);
    RestRequest request = getRestRequest(headers, "/", content);
    long creationTimeMs = System.currentTimeMillis();
    time.setCurrentMilliseconds(creationTimeMs);
    RestResponseChannel restResponseChannel = new MockRestResponseChannel();
    FutureResult<Void> future = new FutureResult<>();
    idConverterFactory.lastInput = null;
    postBlobHandler.handle(request, restResponseChannel, future::done);
    if (errorChecker == null) {
      future.get(TIMEOUT_SECS, TimeUnit.SECONDS);
      assertEquals("Unexpected converted ID", CONVERTED_ID, restResponseChannel.getHeader(RestUtils.Headers.LOCATION));
      Object metadata = request.getArgs().get(RestUtils.InternalKeys.SIGNED_ID_METADATA_KEY);
      if (chunkUpload) {
        Map<String, String> expectedMetadata = new HashMap<>(3);
        expectedMetadata.put(RestUtils.Headers.BLOB_SIZE, Integer.toString(contentLength));
        expectedMetadata.put(RestUtils.Headers.SESSION, uploadSession);
        expectedMetadata.put(PostBlobHandler.EXPIRATION_TIME_MS_KEY,
            Long.toString(Utils.addSecondsToEpochTime(creationTimeMs, blobTtlSecs)));
        if (reservedMetadataId != null) {
          expectedMetadata.put(RestUtils.Headers.RESERVED_METADATA_ID, reservedMetadataId);
        } else {
          assertEquals(
              callCount, ReservedMetadataIdMetrics.getReservedMetadataIdMetrics(
                  metrics.getMetricRegistry()).noReservedMetadataFoundForChunkedUploadResponseCount.getCount());
        }
        assertEquals("Unexpected signed ID metadata", expectedMetadata, metadata);
      } else {
        assertNull("Signed id metadata should not be set on non-chunk uploads", metadata);
      }
      InMemoryRouter.InMemoryBlob blob = router.getActiveBlobs().get(idConverterFactory.lastInput);
      assertEquals("Unexpected blob content stored", ByteBuffer.wrap(content), blob.getBlob());
      assertEquals("Unexpected ttl stored", blobTtlSecs, blob.getBlobProperties().getTimeToLiveInSeconds());
      //check that blob size matches the actual upload size
      assertEquals("Invalid blob size", Integer.toString(contentLength),
          restResponseChannel.getHeader(RestUtils.Headers.BLOB_SIZE));
    } else {
      TestUtils.assertException(ExecutionException.class, () -> future.get(TIMEOUT_SECS, TimeUnit.SECONDS),
          errorChecker);
    }
  }
Make a post request and verify behavior related to chunk uploads (for stitched blobs).
@param contentLength the size of the blob to upload.
@param chunkUpload {@code true} to send the "x-ambry-chunk-upload" header, or {@code false} to test full uploads.
@param uploadSession the value for the "x-ambry-chunk-upload-session" request header, or null to not set it.
@param maxUploadSize the value for the "x-ambry-max-upload-size" request header, or null to not set it.
@param blobTtlSecs the blob TTL to use.
@param errorChecker if non-null, expect an exception to be thrown by the post flow and verify it using this
                    {@link ThrowingConsumer}.
@param callCount number of times this method is called.
@throws Exception
ambry-frontend/src/test/java/com/github/ambry/frontend/PostBlobHandlerTest.java