@Override
    public void receiveFlowControlledFrame(Http2Stream stream, ByteBuf data, int padding,
            boolean endOfStream) throws Http2Exception {
        assert ctx != null && ctx.executor().inEventLoop();
        int dataLength = data.readableBytes() + padding;

        // Apply the connection-level flow control
        FlowState connectionState = connectionState();
        connectionState.receiveFlowControlledFrame(dataLength);

        if (stream != null && !isClosed(stream)) {
            // Apply the stream-level flow control
            FlowState state = state(stream);
            state.endOfStream(endOfStream);
            state.receiveFlowControlledFrame(dataLength);
        } else if (dataLength > 0) {
            // Immediately consume the bytes for the connection window.
            connectionState.consumeBytes(dataLength);
        }
    }
@Test
    public void windowUpdateShouldBeWrittenWhenStreamIsClosedAndFlushed() throws Http2Exception {
        int dataSize = (int) (DEFAULT_WINDOW_SIZE * DEFAULT_WINDOW_UPDATE_RATIO) + 1;

        setupChannelHandlerContext(true);

        receiveFlowControlledFrame(STREAM_ID, dataSize, 0, false);
        verifyWindowUpdateNotSent(CONNECTION_STREAM_ID);
        verifyWindowUpdateNotSent(STREAM_ID);

        connection.stream(STREAM_ID).close();

        verifyWindowUpdateSent(CONNECTION_STREAM_ID, dataSize);

        // Verify we saw one flush.
        verify(ctx).flush();
    }