@Test
  public void stitchedUploadTest() throws Exception {
    idConverterFactory.translation = CONVERTED_ID;
    String uploadSession = UUID.randomUUID().toString();
    long creationTimeMs = System.currentTimeMillis();
    time.setCurrentMilliseconds(creationTimeMs);

    String[] prefixToTest = new String[]{"/" + CLUSTER_NAME, ""};
    for (String prefix : prefixToTest) {
      // success cases
      // multiple chunks
      List<ChunkInfo> chunksToStitch = uploadChunksViaRouter(creationTimeMs, REF_CONTAINER, 45, 10, 200, 19, 0, 50);
      List<String> signedChunkIds = chunksToStitch.stream()
          .map(chunkInfo -> prefix + getSignedId(chunkInfo, uploadSession))
          .collect(Collectors.toList());
      stitchBlobAndVerify(getStitchRequestBody(signedChunkIds), chunksToStitch, null);
      // one chunk
      chunksToStitch = uploadChunksViaRouter(creationTimeMs, REF_CONTAINER, 45);
      signedChunkIds = chunksToStitch.stream()
          .map(chunkInfo -> prefix + getSignedId(chunkInfo, uploadSession))
          .collect(Collectors.toList());
      stitchBlobAndVerify(getStitchRequestBody(signedChunkIds), chunksToStitch, null);

      // failure cases
      // invalid json input
      stitchBlobAndVerify("badjsonbadjson".getBytes(StandardCharsets.UTF_8), null,
          restServiceExceptionChecker(RestServiceErrorCode.BadRequest));
      // no chunk ids in request
      stitchBlobAndVerify(getStitchRequestBody(Collections.emptyList()), null,
          restServiceExceptionChecker(RestServiceErrorCode.MissingArgs));
      stitchBlobAndVerify(new JSONObject().toString().getBytes(StandardCharsets.UTF_8), null,
          restServiceExceptionChecker(RestServiceErrorCode.MissingArgs));
      // differing session IDs
      signedChunkIds = uploadChunksViaRouter(creationTimeMs, REF_CONTAINER, 45, 22).stream()
          .map(chunkInfo -> prefix + getSignedId(chunkInfo, UUID.randomUUID().toString()))
          .collect(Collectors.toList());
      stitchBlobAndVerify(getStitchRequestBody(signedChunkIds), null,
          restServiceExceptionChecker(RestServiceErrorCode.BadRequest));
      // differing containers
      signedChunkIds = Stream.concat(uploadChunksViaRouter(creationTimeMs, REF_CONTAINER, 50, 50).stream(),
          uploadChunksViaRouter(creationTimeMs, REF_CONTAINER_WITH_TTL_REQUIRED, 50).stream())
          .map(chunkInfo -> prefix + getSignedId(chunkInfo, uploadSession))
          .collect(Collectors.toList());
      stitchBlobAndVerify(getStitchRequestBody(signedChunkIds), null,
          restServiceExceptionChecker(RestServiceErrorCode.BadRequest));
      // differing accounts
      Container altAccountContainer =
          ACCOUNT_SERVICE.createAndAddRandomAccount().getContainerById(Container.DEFAULT_PRIVATE_CONTAINER_ID);
      signedChunkIds = Stream.concat(uploadChunksViaRouter(creationTimeMs, REF_CONTAINER, 50, 50).stream(),
          uploadChunksViaRouter(creationTimeMs, altAccountContainer, 50).stream())
          .map(chunkInfo -> prefix + getSignedId(chunkInfo, uploadSession))
          .collect(Collectors.toList());
      stitchBlobAndVerify(getStitchRequestBody(signedChunkIds), null,
          restServiceExceptionChecker(RestServiceErrorCode.BadRequest));
      // invalid blob ID
      stitchBlobAndVerify(
          getStitchRequestBody(Collections.singletonList(getSignedId(new ChunkInfo("abcd", 200, -1, null), uploadSession))),
          null, restServiceExceptionChecker(RestServiceErrorCode.BadRequest));
      // unsigned ID
      stitchBlobAndVerify(getStitchRequestBody(Collections.singletonList("/notASignedId")), null,
          restServiceExceptionChecker(RestServiceErrorCode.BadRequest));
    }
  }
Test flows related to the {@link Operations#STITCH} operation.
@throws Exception
ambry-frontend/src/test/java/com/github/ambry/frontend/PostBlobHandlerTest.java