@Override
 public void handlerRemoved(ChannelHandlerContext ctx) throws Exception {
   if (channelBuffer.refCnt() >= 1) {
     channelBuffer.release();
   }
   super.handlerRemoved(ctx);
 }
  @Test
  public void shouldFireChannelWritabilityChangedAfterRemoval() {
    final AtomicReference<ChannelHandlerContext> ctxRef =
        new AtomicReference<ChannelHandlerContext>();
    final AtomicReference<PendingWriteQueue> queueRef = new AtomicReference<PendingWriteQueue>();
    final ByteBuf msg = Unpooled.copiedBuffer("test", CharsetUtil.US_ASCII);

    final EmbeddedChannel channel =
        new EmbeddedChannel(
            new ChannelHandlerAdapter() {
              @Override
              public void handlerAdded(ChannelHandlerContext ctx) throws Exception {
                ctxRef.set(ctx);
                queueRef.set(new PendingWriteQueue(ctx));
              }

              @Override
              public void channelWritabilityChanged(ChannelHandlerContext ctx) throws Exception {
                final PendingWriteQueue queue = queueRef.get();

                final ByteBuf msg = (ByteBuf) queue.current();
                if (msg == null) {
                  return;
                }

                assertThat(msg.refCnt(), is(1));

                // This call will trigger another channelWritabilityChanged() event because the
                // number of
                // pending bytes will go below the low watermark.
                //
                // If PendingWriteQueue.remove() did not remove the current entry before triggering
                // channelWritabilityChanged() event, we will end up with attempting to remove the
                // same
                // element twice, resulting in the double release.
                queue.remove();

                assertThat(msg.refCnt(), is(0));
              }
            });

    channel.config().setWriteBufferLowWaterMark(1);
    channel.config().setWriteBufferHighWaterMark(3);

    final PendingWriteQueue queue = queueRef.get();

    // Trigger channelWritabilityChanged() by adding a message that's larger than the high
    // watermark.
    queue.add(msg, channel.newPromise());

    channel.finish();

    assertThat(msg.refCnt(), is(0));
  }
 @Test
 public void echo() {
   String m = "echo test\n";
   EmbeddedChannel ch = new EmbeddedChannel(new EchoServerHandler());
   ByteBuf in = Unpooled.copiedBuffer(m, CharsetUtil.UTF_8);
   ch.writeInbound(in);
   ByteBuf r = (ByteBuf) ch.readOutbound();
   releaseLater(r);
   assertThat("응답이 없습니다", r, notNullValue());
   assertThat("참조수는 1이어야 합니다", r.refCnt(), is(1));
   assertThat("수신한 텍스트가 결과로 와야합니다", r.toString(CharsetUtil.UTF_8), equalTo(m));
 }
 private void handleError(@NotNull FastCgiRequest fastCgiRequest, @Nullable ByteBuf content) {
   try {
     if (content != null && content.refCnt() != 0) {
       content.release();
     }
   } finally {
     Channel channel = requests.remove(fastCgiRequest.requestId);
     if (channel != null) {
       sendBadGateway(channel);
     }
   }
 }
 @Override
 public int refCnt() {
   return buf.refCnt();
 }
 @Override
 public int refCnt() {
   return content.refCnt();
 }