@Test
  public void testStitchErrorDataChunkHandling() throws Exception {
    BlobProperties blobProperties =
        new BlobProperties(-1, "serviceId", "memberId", "contentType", false, Utils.Infinite_Time,
            Utils.getRandomShort(TestUtils.RANDOM), Utils.getRandomShort(TestUtils.RANDOM), false, null, null, null);
    byte[] userMetadata = new byte[10];
    FutureResult<String> future = new FutureResult<>();
    MockNetworkClient mockNetworkClient = new MockNetworkClient();
    List<ChunkInfo> chunksToStitch =
        RouterTestHelpers.buildChunkList(mockClusterMap, BlobId.BlobDataType.DATACHUNK, Utils.Infinite_Time,
            LongStream.of(10, 10, 11));
    PutOperation op =
        PutOperation.forStitching(routerConfig, routerMetrics, mockClusterMap, new LoggingNotificationSystem(),
            new InMemAccountService(true, false), userMetadata, chunksToStitch, future, null,
            new RouterCallback(mockNetworkClient, new ArrayList<>()), null, null, null, time, blobProperties,
            MockClusterMap.DEFAULT_PARTITION_CLASS, quotaChargeCallback, compressionService);
    // Trigger an exception by making the last chunk size too large.
    op.startOperation();
    Assert.assertTrue("Operation should be completed", op.isOperationComplete());
    Assert.assertEquals("Wrong RouterException error code", RouterErrorCode.InvalidPutArgument,
        ((RouterException) op.getOperationException()).getErrorCode());
    // Ensure that the operation does not provide the background deleter with any data chunks to delete.
    Assert.assertEquals("List of chunks to delete should be empty", 0,
        op.getSuccessfullyPutChunkIdsIfCompositeDirectUpload().size());
  }
Ensure that errors while stitching blobs do not result in data chunk deletions.
@throws Exception
ambry-router/src/test/java/com/github/ambry/router/PutOperationTest.java