CombinedChannelDuplexHandler extends ChannelDuplexHandler { public final void removeInboundHandler() { checkAdded(); inboundCtx.remove(); } protected  CombinedChannelDuplexHandler();  CombinedChannelDuplexHandler(I inboundHandler, O outboundHandler); final void removeInboundHandler(); final void removeOutboundHandler(); @Override void handlerAdded(ChannelHandlerContext ctx); @Override void handlerRemoved(ChannelHandlerContext ctx); @Override void channelRegistered(ChannelHandlerContext ctx); @Override void channelUnregistered(ChannelHandlerContext ctx); @Override void channelActive(ChannelHandlerContext ctx); @Override void channelInactive(ChannelHandlerContext ctx); @Override void exceptionCaught(ChannelHandlerContext ctx, Throwable cause); @Override void userEventTriggered(ChannelHandlerContext ctx, Object evt); @Override void channelRead(ChannelHandlerContext ctx, Object msg); @Override void channelReadComplete(ChannelHandlerContext ctx); @Override void channelWritabilityChanged(ChannelHandlerContext ctx); @Override void bind(
            ChannelHandlerContext ctx,
            SocketAddress localAddress, ChannelPromise promise); @Override void connect(
            ChannelHandlerContext ctx,
            SocketAddress remoteAddress, SocketAddress localAddress,
            ChannelPromise promise); @Override void disconnect(ChannelHandlerContext ctx, ChannelPromise promise); @Override void close(ChannelHandlerContext ctx, ChannelPromise promise); @Override void deregister(ChannelHandlerContext ctx, ChannelPromise promise); @Override void read(ChannelHandlerContext ctx); @Override void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise); @Override void flush(ChannelHandlerContext ctx);  }
@Test(expected = IllegalStateException.class) public void testInboundRemoveBeforeAdded() { CombinedChannelDuplexHandler<ChannelInboundHandler, ChannelOutboundHandler> handler = new CombinedChannelDuplexHandler<ChannelInboundHandler, ChannelOutboundHandler>( new ChannelInboundHandlerAdapter(), new ChannelOutboundHandlerAdapter()); handler.removeInboundHandler(); }
@Test public void testInboundEvents() { final Queue<Event> queue = new ArrayDeque<Event>(); ChannelInboundHandler inboundHandler = new ChannelInboundHandlerAdapter() { @Override public void handlerAdded(ChannelHandlerContext ctx) throws Exception { queue.add(Event.HANDLER_ADDED); } @Override public void handlerRemoved(ChannelHandlerContext ctx) throws Exception { queue.add(Event.HANDLER_REMOVED); } @Override public void channelRegistered(ChannelHandlerContext ctx) throws Exception { queue.add(Event.REGISTERED); } @Override public void channelUnregistered(ChannelHandlerContext ctx) throws Exception { queue.add(Event.UNREGISTERED); } @Override public void channelActive(ChannelHandlerContext ctx) throws Exception { queue.add(Event.ACTIVE); } @Override public void channelInactive(ChannelHandlerContext ctx) throws Exception { queue.add(Event.INACTIVE); } @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { queue.add(Event.CHANNEL_READ); } @Override public void channelReadComplete(ChannelHandlerContext ctx) throws Exception { queue.add(Event.CHANNEL_READ_COMPLETE); } @Override public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception { queue.add(Event.USER_EVENT_TRIGGERED); } @Override public void channelWritabilityChanged(ChannelHandlerContext ctx) throws Exception { queue.add(Event.CHANNEL_WRITABILITY_CHANGED); } @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { queue.add(Event.EXCEPTION_CAUGHT); } }; CombinedChannelDuplexHandler<ChannelInboundHandler, ChannelOutboundHandler> handler = new CombinedChannelDuplexHandler<ChannelInboundHandler, ChannelOutboundHandler>( inboundHandler, new ChannelOutboundHandlerAdapter()); EmbeddedChannel channel = new EmbeddedChannel(handler); channel.pipeline().fireChannelWritabilityChanged(); channel.pipeline().fireUserEventTriggered(MSG); channel.pipeline().fireChannelRead(MSG); channel.pipeline().fireChannelReadComplete(); assertEquals(Event.HANDLER_ADDED, queue.poll()); assertEquals(Event.REGISTERED, queue.poll()); assertEquals(Event.ACTIVE, queue.poll()); assertEquals(Event.CHANNEL_WRITABILITY_CHANGED, queue.poll()); assertEquals(Event.USER_EVENT_TRIGGERED, queue.poll()); assertEquals(Event.CHANNEL_READ, queue.poll()); assertEquals(Event.CHANNEL_READ_COMPLETE, queue.poll()); handler.removeInboundHandler(); assertEquals(Event.HANDLER_REMOVED, queue.poll()); channel.pipeline().fireChannelWritabilityChanged(); channel.pipeline().fireUserEventTriggered(MSG); channel.pipeline().fireChannelRead(MSG); channel.pipeline().fireChannelReadComplete(); assertTrue(queue.isEmpty()); assertTrue(channel.finish()); assertTrue(queue.isEmpty()); }