Source:
<code>private void testEarlyReadableStreamChannelClose(int numChunksInBlob, final int numChunksToRead) throws Exception { final AtomicReference<Exception> callbackException = new AtomicReference<>(); final CountDownLatch readCompleteLatch = new CountDownLatch(1); Callback<GetBlobResult> callback = new Callback<GetBlobResult>() { @Override public void onCompletion(final GetBlobResult result, Exception exception) { if (exception != null) { callbackException.set(exception); readCompleteLatch.countDown(); } else { final ByteBufferAsyncWritableChannel writableChannel = new ByteBufferAsyncWritableChannel(); <START> result.getBlobDataChannel().readInto(writableChannel, null); <END> Utils.newThread(new Runnable() { @Override public void run() { try { int chunksLeftToRead = numChunksToRead; while (chunksLeftToRead > 0) { writableChannel.getNextChunk(); writableChannel.resolveOldestChunk(null); chunksLeftToRead--; } result.getBlobDataChannel().close(); } catch (Exception e) { callbackException.set(e); } finally { readCompleteLatch.countDown(); } } }, false).start(); } } }; blobSize = numChunksInBlob * maxChunkSize; doPut(); GetBlobOperation op = createOperationAndComplete(callback); readCompleteLatch.await(); if (callbackException.get() != null) { throw callbackException.get(); } Exception operationException = op.getOperationException(); Assert.assertTrue("Unexpected type for exception: " + operationException, operationException instanceof RouterException); Assert.assertEquals("Unexpected RouterErrorCode", RouterErrorCode.ChannelClosed, ((RouterException) operationException).getErrorCode()); }</code><technical_language>this readInto() get ClosedChannelException (if future returns is checked operation completes)? If so, check for end well</technical_language>

Target:
private void testEarlyReadableStreamChannelClose(int numChunksInBlob, final int numChunksToRead) throws Exception { final AtomicReference<Exception> callbackException = new AtomicReference<>(); final AtomicReference<Future<Long>> readIntoFuture = new AtomicReference<>(); final CountDownLatch readCompleteLatch = new CountDownLatch(1); Callback<GetBlobResult> callback = new Callback<GetBlobResult>() { @Override public void onCompletion(final GetBlobResult result, Exception exception) { if (exception != null) { callbackException.set(exception); readCompleteLatch.countDown(); } else { final ByteBufferAsyncWritableChannel writableChannel = new ByteBufferAsyncWritableChannel(); readIntoFuture.set(result.getBlobDataChannel().readInto(writableChannel, null)); Utils.newThread(new Runnable() { @Override public void run() { try { int chunksLeftToRead = numChunksToRead; while (chunksLeftToRead > 0) { writableChannel.getNextChunk(); writableChannel.resolveOldestChunk(null); chunksLeftToRead--; } result.getBlobDataChannel().close(); } catch (Exception e) { callbackException.set(e); } finally { readCompleteLatch.countDown(); } } }, false).start(); } } }; blobSize = numChunksInBlob * maxChunkSize; doPut(); GetBlobOperation op = createOperationAndComplete(callback); Assert.assertTrue("Timeout waiting for read to complete", readCompleteLatch.await(2, TimeUnit.SECONDS)); if (callbackException.get() != null) { throw callbackException.get(); } try { readIntoFuture.get().get(); Assert.fail("Expected ExecutionException"); } catch (ExecutionException e) { Assert.assertTrue("Unexpected type for exception: " + e.getCause(), e.getCause() instanceof RouterException); Assert.assertEquals("Unexpected RouterErrorCode", RouterErrorCode.ChannelClosed, ((RouterException) e.getCause()).getErrorCode()); } Exception operationException = op.getOperationException(); Assert.assertTrue("Unexpected type for exception: " + operationException, operationException instanceof RouterException); Assert.assertEquals("Unexpected RouterErrorCode", RouterErrorCode.ChannelClosed, ((RouterException) operationException).getErrorCode()); }