protected S state() {
        return state;
    }
@Test
    public void testChannelInputShutdownEvent() {
        final AtomicReference<Error> error = new AtomicReference<Error>();

        EmbeddedChannel channel = new EmbeddedChannel(new ReplayingDecoder<Integer>(0) {
            private boolean decoded;

            @Override
            protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
                if (!(in instanceof ReplayingDecoderByteBuf)) {
                    error.set(new AssertionError("in must be of type " + ReplayingDecoderByteBuf.class
                            + " but was " + in.getClass()));
                    return;
                }
                if (!decoded) {
                    decoded = true;
                    in.readByte();
                    state(1);
                } else {
                    // This will throw an ReplayingError
                    in.skipBytes(Integer.MAX_VALUE);
                }
            }
        });

        assertFalse(channel.writeInbound(Unpooled.wrappedBuffer(new byte[] {0, 1})));
        channel.pipeline().fireUserEventTriggered(ChannelInputShutdownEvent.INSTANCE);
        assertFalse(channel.finishAndReleaseAll());

        Error err = error.get();
        if (err != null) {
            throw err;
        }
    }