public void CanSendGoAwayUsingVoidPromise()
        {
            _handler = NewHandler();
            IByteBuffer data      = DummyData();
            var         errorCode = Http2Error.InternalError;

            _handler = NewHandler();
            var cause = new Http2RuntimeException("fake exception");

            _frameWriter
            .Setup(x => x.WriteGoAwayAsync(
                       It.IsAny <IChannelHandlerContext>(),
                       It.IsAny <int>(),
                       It.IsAny <Http2Error>(),
                       It.IsAny <IByteBuffer>(),
                       It.IsAny <IPromise>()
                       ))
            .Returns <IChannelHandlerContext, int, Http2Error, IByteBuffer, IPromise>((c, id, err, buf, p) =>
            {
                Assert.False(p.IsVoid);
                // This is what DefaultHttp2FrameWriter does... I hate mocking :-(.
                var aggregatedPromise = new SimplePromiseAggregator(p);
                aggregatedPromise.NewPromise();
                aggregatedPromise.DoneAllocatingPromises();
                aggregatedPromise.SetException(cause);
                return(aggregatedPromise.Task);
            });
            _handler.GoAwayAsync(_ctx.Object, STREAM_ID, errorCode, data, Http2TestUtil.NewVoidPromise(_channel.Object));
            _pipeline.Verify(x => x.FireExceptionCaught(It.Is <Exception>(v => ReferenceEquals(v, cause))));
        }
        private void WriteRstStreamUsingVoidPromise(int streamId)
        {
            _handler = NewHandler();
            var cause = new Http2RuntimeException("fake exception");

            _stream.Setup(x => x.Id).Returns(STREAM_ID);
            _frameWriter
            .Setup(x => x.WriteRstStreamAsync(
                       It.Is <IChannelHandlerContext>(v => v == _ctx.Object),
                       It.Is <int>(v => v == streamId),
                       It.IsAny <Http2Error>(),
                       It.IsAny <IPromise>()))
            .Returns <IChannelHandlerContext, int, Http2Error, IPromise>((ctx, id, err, p) =>
            {
                Assert.False(p.IsVoid);
                p.SetException(cause);
                return(p.Task);
            });
            _handler.ResetStreamAsync(_ctx.Object, streamId, Http2Error.StreamClosed, Http2TestUtil.NewVoidPromise(_channel.Object));
            _frameWriter.Verify(
                x => x.WriteRstStreamAsync(
                    It.Is <IChannelHandlerContext>(v => v == _ctx.Object),
                    It.Is <int>(v => v == streamId),
                    It.IsAny <Http2Error>(),
                    It.IsAny <IPromise>()));
            _pipeline.Verify(x => x.FireExceptionCaught(It.Is <Exception>(v => ReferenceEquals(v, cause))));
        }
        public void ConnectionErrorForWriterException()
        {
            this.InitState(STREAM_A, 1, true);
            this.InitState(STREAM_B, 2, true);
            this.InitState(STREAM_C, 3, true);
            this.InitState(STREAM_D, 4, true);

            Exception fakeException = new Http2RuntimeException("Fake exception");

            this.writer
            .Setup(x => x.Write(
                       It.Is <IHttp2Stream>(v => ReferenceEquals(v, this.Stream(STREAM_C))),
                       It.Is <int>(v => v == 3)))
            .Throws(fakeException);

            try
            {
                this.Write(10);
                Assert.False(true, "Expected an exception");
            }
            catch (Http2Exception e)
            {
                Assert.False(Http2Exception.IsStreamError(e));
                Assert.Equal(Http2Error.InternalError, e.Error);
                Assert.Same(fakeException, e.InnerException);
            }

            this.VerifyWrite(Times.AtMost(1), STREAM_A, 1);
            this.VerifyWrite(Times.AtMost(1), STREAM_B, 2);
            this.VerifyWrite(STREAM_C, 3);
            this.VerifyWrite(Times.AtMost(1), STREAM_D, 4);

            this.writer
            .Setup(x => x.Write(
                       It.Is <IHttp2Stream>(v => ReferenceEquals(v, this.Stream(STREAM_C))),
                       It.Is <int>(v => v == 3)))
            .Callback <IHttp2Stream, int>((stream, numBytes) => this.WriteAnswer(stream, numBytes, false));
            Assert.False(this.Write(10));
            this.VerifyWrite(STREAM_A, 1);
            this.VerifyWrite(STREAM_B, 2);
            this.VerifyWrite(Times.Exactly(2), STREAM_C, 3);
            this.VerifyWrite(STREAM_D, 4);
        }
        public Http2ConnectionHandlerTest()
        {
            _connection           = new Mock <IHttp2Connection>();
            _remoteFlow           = new Mock <IHttp2RemoteFlowController>();
            _localFlow            = new Mock <IHttp2LocalFlowController>();
            _remote               = new Mock <IHttp2ConnectionEndpoint <IHttp2RemoteFlowController> >();
            _remoteFlowController = new Mock <IHttp2RemoteFlowController>();
            _local = new Mock <IHttp2ConnectionEndpoint <IHttp2LocalFlowController> >();
            _localFlowController = new Mock <IHttp2LocalFlowController>();
            _ctx         = new Mock <IChannelHandlerContext>();
            _executor    = new Mock <IEventExecutor>();
            _channel     = new Mock <IChannel>();
            _pipeline    = new Mock <IChannelPipeline>();
            _stream      = new Mock <IHttp2Stream>();
            _decoder     = new Mock <IHttp2ConnectionDecoder>();
            _encoder     = new Mock <IHttp2ConnectionEncoder>();
            _frameWriter = new Mock <IHttp2FrameWriter>();

            _channel.Setup(x => x.Metadata).Returns(new ChannelMetadata(false));
            var config = new DefaultChannelConfiguration(_channel.Object);

            _channel.Setup(x => x.Configuration).Returns(config);

            _promise     = new TaskCompletionSource();
            _voidPromise = new TaskCompletionSource();
            var fakeException = new Http2RuntimeException("Fake exception");

            _future = TaskUtil.FromException(fakeException);

            _encoder.Setup(x => x.Connection).Returns(_connection.Object);
            _decoder.Setup(x => x.Connection).Returns(_connection.Object);
            _encoder.Setup(x => x.FrameWriter).Returns(_frameWriter.Object);
            _encoder.Setup(x => x.FlowController).Returns(_remoteFlow.Object);
            _decoder.Setup(x => x.FlowController).Returns(_localFlow.Object);
            _frameWriter
            .Setup(x => x.WriteGoAwayAsync(
                       It.IsAny <IChannelHandlerContext>(),
                       It.IsAny <int>(),
                       It.IsAny <Http2Error>(),
                       It.IsAny <IByteBuffer>(),
                       It.IsAny <IPromise>()))
            .Returns <IChannelHandlerContext, int, Http2Error, IByteBuffer, IPromise>((ctx, id, err, buf, p) =>
            {
                _goAwayDebugCap = buf.ToString(Encoding.UTF8);
                buf.Release();
                return(_future);
            });
            _channel.Setup(x => x.IsActive).Returns(true);
            _channel.Setup(x => x.Pipeline).Returns(_pipeline.Object);
            _connection.Setup(x => x.Remote).Returns(_remote.Object);
            _remote.Setup(x => x.FlowController).Returns(_remoteFlowController.Object);
            _connection.Setup(x => x.Local).Returns(_local.Object);
            _local.Setup(x => x.FlowController).Returns(_localFlowController.Object);
            _connection
            .Setup(x => x.ForEachActiveStream(It.IsAny <IHttp2StreamVisitor>()))
            .Returns <IHttp2StreamVisitor>(visitor =>
            {
                if (!visitor.Visit(_stream.Object))
                {
                    return(_stream.Object);
                }
                return(null);
            });
            _connection
            .Setup(x => x.ForEachActiveStream(It.IsAny <Func <IHttp2Stream, bool> >()))
            .Returns <Func <IHttp2Stream, bool> >(visitor =>
            {
                if (!visitor(_stream.Object))
                {
                    return(_stream.Object);
                }
                return(null);
            });
            _connection.Setup(x => x.Stream(It.Is <int>(v => v == NON_EXISTANT_STREAM_ID))).Returns(default(IHttp2Stream));
            _connection.Setup(x => x.NumActiveStreams).Returns(1);
            _connection.Setup(x => x.Stream(It.Is <int>(v => v == STREAM_ID))).Returns(_stream.Object);
            _connection
            .Setup(x => x.GoAwaySent(
                       It.IsAny <int>(),
                       It.IsAny <Http2Error>(),
                       It.IsAny <IByteBuffer>()))
            .Returns(true);
            _stream.Setup(x => x.Open(It.IsAny <bool>())).Returns(_stream.Object);
            _encoder
            .Setup(x => x.WriteSettingsAsync(
                       It.Is <IChannelHandlerContext>(v => v == _ctx.Object),
                       It.IsAny <Http2Settings>(),
                       It.Is <IPromise>(v => v == _promise)))
            .Returns(_future);
            _ctx.Setup(x => x.Allocator).Returns(UnpooledByteBufferAllocator.Default);
            _ctx.Setup(x => x.Channel).Returns(_channel.Object);
            _ctx.Setup(x => x.NewPromise()).Returns(_promise);
            _ctx.Setup(x => x.VoidPromise()).Returns(_voidPromise);
            _ctx.Setup(x => x.WriteAsync(It.IsAny <object>())).Returns(_future);
            _ctx.Setup(x => x.Executor).Returns(_executor.Object);
            _ctx
            .Setup(x => x.FireChannelRead(It.IsAny <object>()))
            .Returns <object>(msg =>
            {
                ReferenceCountUtil.Release(msg);
                return(_ctx.Object);
            });
        }