Repository: netty/netty
File: testsuite/src/main/java/io/netty/testsuite/transport/socket/SocketHalfClosedTest.java (Java)

Code before:
                }
                allDataReadEventTriggeredAfterHalfClosure(serverBootstrap, bootstrap);
            }
        });
    }

    private void allDataReadEventTriggeredAfterHalfClosure(ServerBootstrap sb, Bootstrap cb) throws Throwable {
        final int totalServerBytesWritten = 1;
        final CountDownLatch clientReadAllDataLatch = new CountDownLatch(1);
        final CountDownLatch clientHalfClosedLatch = new CountDownLatch(1);
        final CountDownLatch clientHalfClosedAllBytesRead = new CountDownLatch(1);
        final AtomicInteger clientReadCompletes = new AtomicInteger();
        final AtomicInteger clientZeroDataReadCompletes = new AtomicInteger();
        Channel serverChannel = null;
        Channel clientChannel = null;
        AtomicReference<Channel> serverChildChannel = new AtomicReference<>();
        try {
            cb.option(ChannelOption.ALLOW_HALF_CLOSURE, true)
                    .option(ChannelOption.AUTO_CLOSE, false)
                    .option(ChannelOption.AUTO_READ, false);

            sb.childHandler(new ChannelInitializer<Channel>() {
                @Override
                protected void initChannel(Channel ch) throws Exception {
                    serverChildChannel.set(ch);
                    ch.config().setOption(ChannelOption.ALLOW_HALF_CLOSURE, true);
                    ch.pipeline().addLast(new ChannelInboundHandlerAdapter() {
                        @Override
                        public void channelActive(ChannelHandlerContext ctx) throws Exception {
                            ctx.channel().config().setAutoClose(false);
                            ByteBuf buf = ctx.alloc().buffer(totalServerBytesWritten);
                            buf.writerIndex(buf.capacity());
                            ctx.writeAndFlush(buf);
                        }

                        @Override
                        public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
                            ctx.close();
                        }
                    });
                }
            });

            // client.
            cb.handler(new ChannelInitializer<Channel>() {
                @Override
                protected void initChannel(Channel ch) {
                    ch.config().setAutoClose(false);
                    ch.pipeline().addLast(new ChannelInboundHandlerAdapter() {
                        private int bytesRead;
                        private int bytesSinceReadComplete;

Review comment (suggestion):
You could set this a priori as a child option on `sb`

Code after:
                    logger.debug("Ignoring test for incompatible OIO event system");
                    return;
                } else if (bootstrap.config().group() instanceof IoEventLoopGroup) {
                    IoEventLoopGroup group = (IoEventLoopGroup) bootstrap.config().group();
                    if (group.isIoType(NioIoHandler.class)) {
                        logger.debug("Ignoring test for incompatible NioHandler");
                        return;
                    }
                }
                allDataReadEventTriggeredAfterHalfClosure(serverBootstrap, bootstrap);
            }
        });
    }

    private void allDataReadEventTriggeredAfterHalfClosure(ServerBootstrap sb, Bootstrap cb) throws Throwable {
        final int totalServerBytesWritten = 1;
        final CountDownLatch clientReadAllDataLatch = new CountDownLatch(1);
        final CountDownLatch clientHalfClosedLatch = new CountDownLatch(1);
        final CountDownLatch clientHalfClosedAllBytesRead = new CountDownLatch(1);
        final AtomicInteger clientReadCompletes = new AtomicInteger();
        final AtomicInteger clientZeroDataReadCompletes = new AtomicInteger();
        Channel serverChannel = null;
        Channel clientChannel = null;
        AtomicReference<Channel> serverChildChannel = new AtomicReference<>();
        try {
            cb.option(ChannelOption.ALLOW_HALF_CLOSURE, true)
                    .option(ChannelOption.AUTO_CLOSE, false)
                    .option(ChannelOption.AUTO_READ, false);

            sb.option(ChannelOption.ALLOW_HALF_CLOSURE, true)
                    .option(ChannelOption.AUTO_CLOSE, false)
                    .childOption(ChannelOption.TCP_NODELAY, true);

            sb.childHandler(new ChannelInitializer<Channel>() {
                @Override
                protected void initChannel(Channel ch) throws Exception {
                    serverChildChannel.set(ch);
                    ch.pipeline().addLast(new ChannelInboundHandlerAdapter() {
                        @Override
                        public void channelActive(ChannelHandlerContext ctx) throws Exception {
                            ByteBuf buf = ctx.alloc().buffer(totalServerBytesWritten);
                            buf.writerIndex(buf.capacity());
                            ctx.writeAndFlush(buf);
                        }

                        @Override
                        public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
                            ctx.close();
                        }
                    });
                }