@Override
    public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception {
        if (!queueIsEmpty() || msg instanceof ChunkedInput) {
            allocateQueue();
            queue.add(new PendingWrite(msg, promise));
        } else {
            ctx.write(msg, promise);
        }
    }
@Test
    public void testFailureWhenLastChunkFailed() throws IOException {
        ChannelOutboundHandlerAdapter failLast = new ChannelOutboundHandlerAdapter() {
            private int passedWrites;

            @Override
            public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) {
                if (++this.passedWrites < 4) {
                    ctx.write(msg, promise);
                } else {
                    ReferenceCountUtil.release(msg);
                    promise.tryFailure(new RuntimeException());
                }
            }
        };

        EmbeddedChannel ch = new EmbeddedChannel(failLast, new ChunkedWriteHandler());
        ChannelFuture r = ch.writeAndFlush(new ChunkedFile(TMP, 1024 * 16)); // 4 chunks
        assertTrue(ch.finish());

        assertFalse(r.isSuccess());
        assertTrue(r.cause() instanceof RuntimeException);

        // 3 out of 4 chunks were already written
        int read = 0;
        for (;;) {
            ByteBuf buffer = ch.readOutbound();
            if (buffer == null) {
                break;
            }
            read += buffer.readableBytes();
            buffer.release();
        }

        assertEquals(1024 * 16 * 3, read);
    }