### Question:
Http2ConnectionHandler extends ByteToMessageDecoder implements Http2LifecycleManager,
                                                                            ChannelOutboundHandler { @Override public void handlerAdded(ChannelHandlerContext ctx) throws Exception { encoder.lifecycleManager(this); decoder.lifecycleManager(this); encoder.flowController().channelHandlerContext(ctx); decoder.flowController().channelHandlerContext(ctx); byteDecoder = new PrefaceDecoder(ctx); } protected  Http2ConnectionHandler(Http2ConnectionDecoder decoder, Http2ConnectionEncoder encoder,
                                     Http2Settings initialSettings);   Http2ConnectionHandler(boolean server, Http2FrameWriter frameWriter, Http2FrameLogger frameLogger,
                    Http2Settings initialSettings); long gracefulShutdownTimeoutMillis(); void gracefulShutdownTimeoutMillis(long gracefulShutdownTimeoutMillis); Http2Connection connection(); Http2ConnectionDecoder decoder(); Http2ConnectionEncoder encoder(); void onHttpClientUpgrade(); void onHttpServerUpgrade(Http2Settings settings); @Override void flush(ChannelHandlerContext ctx); @Override void handlerAdded(ChannelHandlerContext ctx); @Override void channelActive(ChannelHandlerContext ctx); @Override void channelInactive(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 channelReadComplete(ChannelHandlerContext ctx); @Override void exceptionCaught(ChannelHandlerContext ctx, Throwable cause); @Override void closeStreamLocal(Http2Stream stream, ChannelFuture future); @Override void closeStreamRemote(Http2Stream stream, ChannelFuture future); @Override void closeStream(final Http2Stream stream, ChannelFuture future); @Override void onError(ChannelHandlerContext ctx, boolean outbound, Throwable cause); @Override ChannelFuture resetStream(final ChannelHandlerContext ctx, int streamId, long errorCode,
                                     ChannelPromise promise); @Override ChannelFuture goAway(final ChannelHandlerContext ctx, final int lastStreamId, final long errorCode,
                                final ByteBuf debugData, ChannelPromise promise);  }### Answer:
@Test public void verifyChannelHandlerCanBeReusedInPipeline() throws Exception { when(connection.isServer()).thenReturn(true); handler = newHandler(); ByteBuf preface = connectionPrefaceBuf(); handler.channelRead(ctx, preface); verify(decoder, never()).decodeFrame(any(ChannelHandlerContext.class), any(ByteBuf.class), ArgumentMatchers.<List<Object>>any()); handler.handlerRemoved(ctx); handler.handlerAdded(ctx); ByteBuf prefacePlusSome = addSettingsHeader(Unpooled.buffer().writeBytes(connectionPrefaceBuf())); handler.channelRead(ctx, prefacePlusSome); verify(decoder, atLeastOnce()).decodeFrame(eq(ctx), any(ByteBuf.class), ArgumentMatchers.<List<Object>>any()); }
@Test public void prefaceUserEventProcessed() throws Exception { final CountDownLatch latch = new CountDownLatch(1); handler = new Http2ConnectionHandler(decoder, encoder, new Http2Settings()) { @Override public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception { if (evt == Http2ConnectionPrefaceAndSettingsFrameWrittenEvent.INSTANCE) { latch.countDown(); } } }; handler.handlerAdded(ctx); assertTrue(latch.await(5, SECONDS)); }