@Test
  public void testEmptyByteBufInReadableStreamChannel() 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];
    byte[] content = new byte[chunkSize];
    random.nextBytes(content);
    ReadableStreamChannel channel = new ByteBufferReadableStreamChannel(ByteBuffer.wrap(content), true);
    FutureResult<String> future = new FutureResult<>();
    MockNetworkClient mockNetworkClient = new MockNetworkClient();
    PutOperation op =
        PutOperation.forUpload(routerConfig, routerMetrics, mockClusterMap, new LoggingNotificationSystem(),
            new InMemAccountService(true, false), userMetadata, channel, PutBlobOptions.DEFAULT, future, null,
            new RouterCallback(mockNetworkClient, new ArrayList<>()), null, null, null, null, time, blobProperties,
            MockClusterMap.DEFAULT_PARTITION_CLASS, quotaChargeCallback, compressionService);
    op.startOperation();
    // Calling fillChunks would fetch the buffer chunk and the empty chunk from the channel
    op.fillChunks();
    // Now fail the operation
    op.setOperationCompleted();
    // Calling fillChunks again, this would force fillChunk to release the empty chunk
    op.fillChunks();
    // Now call fillChunk again
    op.fillChunks();
    Assert.assertNull(op.getOperationException());
  }
Test the case when there is an empty bytebuf in the end of the {@link ReadableByteChannel}, make sure that
setting operation completed to true wouldn't end up with NPE.
@throws Exception
ambry-router/src/test/java/com/github/ambry/router/PutOperationTest.java