public async Task Retry_MessageHasBeenTouchedTransientExceptionOccured_Success()
        {
            int callCounter = 0;

            var innerHandlerMock = Substitute.For<IDelegatingHandler>();
            var message = new Message(new MemoryStream(new byte[] {1,2,3}));
            innerHandlerMock.SendEventAsync(Arg.Is(message)).Returns(t =>
            {
                callCounter++;

                var m = t.Arg<Message>();
                Stream stream = m.GetBodyStream();
                if (callCounter == 1)
                {
                    throw new IotHubClientTransientException("");
                }
                var buffer = new byte[3];
                stream.Read(buffer, 0, 3);
                return TaskConstants.Completed;
            });

            var sut = new RetryDelegatingHandler(innerHandlerMock);
            await sut.SendEventAsync(message);

            Assert.AreEqual(2, callCounter);
        }
        public async Task Retry_TransientErrorOccured_Retried()
        {
            int callCounter = 0;

            var innerHandlerMock = Substitute.For<IDelegatingHandler>();
            innerHandlerMock.OpenAsync(true).Returns(t =>
            {
                callCounter++;

                if (callCounter == 1)
                {
                    throw new IotHubClientTransientException("");
                }
                return TaskConstants.Completed;
            });

            var sut = new RetryDelegatingHandler(innerHandlerMock);
            await sut.OpenAsync(true);

            Assert.AreEqual(2, callCounter);
        }
        DeviceClient(IotHubConnectionString iotHubConnectionString, ITransportSettings[] transportSettings)
        {
            this.iotHubConnectionString = iotHubConnectionString;

#if !WINDOWS_UWP
            var innerHandler = new RetryDelegatingHandler(
                new ErrorDelegatingHandler(
                    () => new RoutingDelegatingHandler(this.CreateTransportHandler, iotHubConnectionString, transportSettings)));
#else
            // UWP does not support retry yet. We need to make the underlying Message stream accessible internally on UWP
            // to be sure that either the stream has not been read or it is seekable to safely retry operation
            var innerHandler = new ErrorDelegatingHandler(
                () => new RoutingDelegatingHandler(this.CreateTransportHandler, iotHubConnectionString, transportSettings));
#endif
            this.InnerHandler = new GateKeeperDelegatingHandler(innerHandler);
        }
        public async Task Retry_MessageHasBeenReadTransientExceptionOccured_Throws()
        {
            int callCounter = 0;

            var innerHandlerMock = Substitute.For<IDelegatingHandler>();
            var memoryStream = new NotSeekableStream(new byte[] {1,2,3});
            var message = new Message(memoryStream);
            innerHandlerMock.SendEventAsync(Arg.Is(message)).Returns(t =>
            {
                callCounter++;
                var m = t.Arg<Message>();
                Stream stream = m.GetBodyStream();
                var buffer = new byte[3];
                stream.Read(buffer, 0, 3);
                throw new IotHubClientTransientException("");
            });

            var sut = new RetryDelegatingHandler(innerHandlerMock);
            await sut.SendEventAsync(message).ExpectedAsync<IotHubClientTransientException>();

            Assert.AreEqual(callCounter, 1);
        }
        public async Task Retry_TransientErrorThrownAfterNumberOfRetries_Throws()
        {
            var innerHandlerMock = Substitute.For<IDelegatingHandler>();
            innerHandlerMock.OpenAsync(Arg.Is(true)).Returns(t =>
            {
                throw new IotHubClientTransientException("");
            });

            var sut = new RetryDelegatingHandler(innerHandlerMock);

            await sut.OpenAsync(true).ExpectedAsync<IotHubClientTransientException>();
        }
        public async Task Retry_NonTransientErrorThrown_Throws()
        {
            int callCounter = 0;

            var innerHandlerMock = Substitute.For<IDelegatingHandler>();
            innerHandlerMock.OpenAsync(true).Returns(t =>
            {
                callCounter++;

                if (callCounter == 1)
                {
                    throw new InvalidOperationException("");
                }
                return TaskConstants.Completed;
            });

            var sut = new RetryDelegatingHandler(innerHandlerMock);

            await sut.OpenAsync(true).ExpectedAsync<InvalidOperationException>();

            Assert.AreEqual(callCounter, 1);
        }