@Test
  public void shouldPropagateDownstreamFlushOnPipelineFutureSuccess() throws Exception {

    context.checking(
        new Expectations() {
          {
            oneOf(upstream)
                .handleUpstream(
                    with(any(ChannelHandlerContext.class)), with(any(PreparationEvent.class)));
            oneOf(upstream)
                .handleUpstream(
                    with(any(ChannelHandlerContext.class)), with(channelState(OPEN, TRUE)));
            oneOf(downstream)
                .handleDownstream(
                    with(any(ChannelHandlerContext.class)), with(any(FlushEvent.class)));
          }
        });

    channelFactory.newChannel(pipeline);
    ChannelFuture executionFuture = execution.getHandlerFuture();
    executionFuture.setSuccess();

    ChannelFuture handlerFuture = handler.getHandlerFuture();
    handlerFuture.sync();

    context.assertIsSatisfied();
  }
  @Before
  public void setUp() throws Exception {
    context =
        new Mockery() {
          {
            setThrowFirstErrorOnAssertIsSatisfied(true);
          }
        };

    upstream = context.mock(ChannelUpstreamHandler.class);
    downstream = context.mock(ChannelDownstreamHandler.class);

    execution = new ExecutionHandler();

    handler = new FlushHandler();

    pipeline =
        pipeline(
            new SimpleChannelHandler() {
              @Override
              public void handleDownstream(ChannelHandlerContext ctx, ChannelEvent evt)
                  throws Exception {
                downstream.handleDownstream(ctx, evt);
                super.handleDownstream(ctx, evt);
              }

              @Override
              public void flushRequested(ChannelHandlerContext ctx, FlushEvent e) {
                ChannelFuture future = e.getFuture();
                future.setSuccess();
              }
            },
            execution,
            handler,
            new SimpleChannelHandler() {
              @Override
              public void handleUpstream(ChannelHandlerContext ctx, ChannelEvent e)
                  throws Exception {
                upstream.handleUpstream(ctx, e);
                super.handleUpstream(ctx, e);
              }

              @Override
              public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e)
                  throws Exception {
                // prevent console error message
              }
            });

    channelFactory = new DefaultLocalClientChannelFactory();
  }
  @Test
  public void shouldNotPropagateDownstreamFlushOnPipelineFutureFailure() throws Exception {

    context.checking(
        new Expectations() {
          {
            oneOf(upstream)
                .handleUpstream(
                    with(any(ChannelHandlerContext.class)), with(any(PreparationEvent.class)));
            oneOf(upstream)
                .handleUpstream(
                    with(any(ChannelHandlerContext.class)), with(channelState(OPEN, TRUE)));
          }
        });

    channelFactory.newChannel(pipeline);
    ChannelFuture executionFuture = execution.getHandlerFuture();
    executionFuture.setFailure(new ChannelException("pipeline already failed"));

    ChannelFuture handlerFuture = handler.getHandlerFuture();
    assertFalse(handlerFuture.isDone());

    context.assertIsSatisfied();
  }
  @Test
  public void shouldPropagateDownstreamMessageOnPipelineFutureSuccess() throws Exception {

    final ChannelBuffer[] expectedArr = new ChannelBuffer[3];
    expectedArr[0] = wrappedBuffer(new byte[] {0x01, 0x02, 0x03});
    expectedArr[1] = copiedBuffer("Hello, world", UTF_8);
    expectedArr[2] = wrappedBuffer(new byte[] {0x01, 0x02, 0x03});
    final ChannelBuffer expected = masker.applyMask(wrappedBuffer(expectedArr));

    context.checking(
        new Expectations() {
          {
            oneOf(upstream)
                .handleUpstream(
                    with(any(ChannelHandlerContext.class)), with(any(PreparationEvent.class)));
            oneOf(upstream)
                .handleUpstream(
                    with(any(ChannelHandlerContext.class)), with(channelState(OPEN, TRUE)));
            oneOf(downstream)
                .handleDownstream(with(any(ChannelHandlerContext.class)), with(message(expected)));
            oneOf(upstream)
                .handleUpstream(
                    with(any(ChannelHandlerContext.class)), with(any(WriteCompletionEvent.class)));
          }
        });

    expression.setValue(environment, new byte[] {0x01, 0x02, 0x03});
    channelFactory.newChannel(pipeline);
    ChannelFuture executionFuture = execution.getHandlerFuture();
    executionFuture.setSuccess();

    ChannelFuture handlerFuture = handler.getHandlerFuture();
    handlerFuture.sync();

    context.assertIsSatisfied();
  }
  @Before
  public void setUp() throws Exception {
    context =
        new Mockery() {
          {
            setThrowFirstErrorOnAssertIsSatisfied(true);
          }
        };
    context.setThreadingPolicy(new Synchroniser());

    upstream = context.mock(ChannelUpstreamHandler.class);
    downstream = context.mock(ChannelDownstreamHandler.class);

    execution = new ExecutionHandler();

    List<MessageEncoder> encoders = new ArrayList<MessageEncoder>();
    encoders.add(new WriteBytesEncoder(new byte[] {0x01, 0x02, 0x03}));
    encoders.add(new WriteTextEncoder("Hello, world", UTF_8));

    ExpressionFactory expressionFactory = ExpressionFactory.newInstance();
    environment = new ExpressionContext();
    expression = expressionFactory.createValueExpression(environment, "${variable}", byte[].class);
    encoders.add(new WriteExpressionEncoder(expression, environment));

    masker = newMasker(maskingKey);
    handler = new WriteHandler(encoders, newMasker(maskingKey));

    pipeline =
        pipeline(
            new SimpleChannelHandler() {
              @Override
              public void handleDownstream(ChannelHandlerContext ctx, ChannelEvent evt)
                  throws Exception {
                downstream.handleDownstream(ctx, evt);
                super.handleDownstream(ctx, evt);
              }

              @Override
              public void writeRequested(ChannelHandlerContext ctx, MessageEvent e)
                  throws Exception {
                Object message = e.getMessage();
                e.getFuture().setSuccess();
                if (message instanceof ChannelBuffer) {
                  ChannelBuffer buf = (ChannelBuffer) message;
                  fireWriteComplete(ctx, buf.readableBytes());
                }
              }
            },
            execution,
            handler,
            new SimpleChannelHandler() {
              @Override
              public void handleUpstream(ChannelHandlerContext ctx, ChannelEvent e)
                  throws Exception {
                upstream.handleUpstream(ctx, e);
                super.handleUpstream(ctx, e);
              }

              @Override
              public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e)
                  throws Exception {
                // prevent console error message
              }
            });

    channelFactory = new DefaultLocalClientChannelFactory();
  }