The following test fails, which indicates behaviour that is surprising to me and I suspect might be a bug:
index d9f5cd5b8d..f8edf63a29 100644
--- a/codec-http/src/test/java/io/netty/handler/codec/http/HttpContentDecompressorTest.java
+++ b/codec-http/src/test/java/io/netty/handler/codec/http/HttpContentDecompressorTest.java
@@ -20,6 +20,7 @@ import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.channel.ChannelOutboundHandlerAdapter;
import io.netty.channel.embedded.EmbeddedChannel;
+import io.netty.handler.flow.FlowControlHandler;
import org.junit.jupiter.api.Test;
import java.util.concurrent.atomic.AtomicInteger;
@@ -70,4 +71,33 @@ public class HttpContentDecompressorTest {
assertEquals(2, readCalled.get());
assertFalse(channel.finishAndReleaseAll());
}
+
+ @Test
+ public void testFlowController() {
+ final AtomicInteger messagesEmitted = new AtomicInteger();
+ final EmbeddedChannel channel = new EmbeddedChannel(
+ new FlowControlHandler(),
+ new HttpContentDecompressor(),
+ new ChannelInboundHandlerAdapter() {
+ @Override
+ public void channelRead(ChannelHandlerContext ctx, Object msg) {
+ messagesEmitted.incrementAndGet();
+ }
+ });
+
+ channel.config().setAutoRead(false);
+
+ final HttpResponse response = new DefaultHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK);
+ response.headers().set(HttpHeaderNames.TRANSFER_ENCODING, HttpHeaderValues.CHUNKED);
+
+ assertFalse(channel.writeInbound(response));
+ assertFalse(channel.writeInbound(new DefaultHttpContent(Unpooled.buffer(1))));
+ assertFalse(channel.writeInbound(new DefaultHttpContent(Unpooled.buffer(1))));
+
+ assertEquals(1, messagesEmitted.get());
+ channel.read();
+ assertEquals(2, messagesEmitted.get());
+ channel.read();
+ assertEquals(3, messagesEmitted.get());
+ }
}
Specifically, with autoread disabled and a FlowControlHandler in place I would expect the pipeline to emit exactly one message per read() but in fact today it emits all three messages at once:
org.opentest4j.AssertionFailedError:
Expected :1
Actual :3
<Click to see difference>
at org.junit.jupiter.api.AssertionFailureBuilder.build(AssertionFailureBuilder.java:151)
at org.junit.jupiter.api.AssertionFailureBuilder.buildAndThrow(AssertionFailureBuilder.java:132)
at org.junit.jupiter.api.AssertEquals.failNotEqual(AssertEquals.java:197)
at org.junit.jupiter.api.AssertEquals.assertEquals(AssertEquals.java:150)
at org.junit.jupiter.api.AssertEquals.assertEquals(AssertEquals.java:145)
at org.junit.jupiter.api.Assertions.assertEquals(Assertions.java:527)
at io.netty.handler.codec.http.HttpContentDecompressorTest.testFlowController(HttpContentDecompressorTest.java:97)
...
This is happening because the FlowControlHandler fabricates its own READ COMPLETE messages when it empties its queue, but also passes through the READ COMPLETE message from upstream when its internal queue is empty, so the HttpContentDecompressor sees two READ COMPLETE events after processing the first READ. The first such event sets HttpContentDecoder#needRead to true and then the second of them triggers another ctx.read().
Unfortunately I'm not sure whether the problem is that FlowControlHandler emits two READ COMPLETE events in a row without any intervening READ, or if this is expected but HttpContentDecoder should be able to handle those events without triggering another ctx.read(), or indeed if this overall behaviour is expected and I'm just holding it wrong somehow.
The following test fails, which indicates behaviour that is surprising to me and I suspect might be a bug:
Specifically, with autoread disabled and a
FlowControlHandlerin place I would expect the pipeline to emit exactly one message perread()but in fact today it emits all three messages at once:This is happening because the
FlowControlHandlerfabricates its ownREAD COMPLETEmessages when it empties its queue, but also passes through theREAD COMPLETEmessage from upstream when its internal queue is empty, so theHttpContentDecompressorsees twoREAD COMPLETEevents after processing the firstREAD. The first such event setsHttpContentDecoder#needReadtotrueand then the second of them triggers anotherctx.read().Unfortunately I'm not sure whether the problem is that
FlowControlHandleremits twoREAD COMPLETEevents in a row without any interveningREAD, or if this is expected butHttpContentDecodershould be able to handle those events without triggering anotherctx.read(), or indeed if this overall behaviour is expected and I'm just holding it wrong somehow.