public async Task RetrySetRetryPolicyVerifyInternalsSuccess()
        {
            // arrange
            var innerHandlerMock = Substitute.For <IDelegatingHandler>();
            var contextMock      = Substitute.For <PipelineContext>();

            contextMock.ConnectionStatusChangesHandler = new ConnectionStatusChangesHandler(delegate(ConnectionStatus status, ConnectionStatusChangeReason reason) { });
            var sut = new RetryDelegatingHandler(contextMock, innerHandlerMock);

            var retryPolicy = new TestRetryPolicy();

            sut.SetRetryPolicy(retryPolicy);

            int innerHandlerCallCounter = 0;

            innerHandlerMock.OpenAsync(Arg.Any <CancellationToken>()).Returns(t =>
            {
                innerHandlerCallCounter++;
                throw new IotHubCommunicationException();
            });

            // act and assert
            await sut.OpenAsync(CancellationToken.None).ExpectedAsync <IotHubCommunicationException>().ConfigureAwait(false);

            innerHandlerCallCounter.Should().Be(2);
            retryPolicy.Counter.Should().Be(2);

            var noretry = new NoRetry();

            sut.SetRetryPolicy(noretry);
            await sut.OpenAsync(CancellationToken.None).ExpectedAsync <IotHubCommunicationException>().ConfigureAwait(false);

            innerHandlerCallCounter.Should().Be(3);
            retryPolicy.Counter.Should().Be(2);
        }
        public async Task OpenAsyncTwoCallersOnlyOneOpenCalled()
        {
            var contextMock = Substitute.For <PipelineContext>();

            contextMock.ConnectionStatusChangesHandler = new ConnectionStatusChangesHandler(delegate(ConnectionStatus status, ConnectionStatusChangeReason reason) { });
            var tcs = new TaskCompletionSource <int>();
            var innerHandlerMock = Substitute.For <IDelegatingHandler>();
            int callCounter      = 0;

            innerHandlerMock.OpenAsync(Arg.Any <CancellationToken>()).Returns(t =>
            {
                callCounter++;
                return(tcs.Task);
            });
            innerHandlerMock.WaitForTransportClosedAsync().Returns(Task.Delay(TimeSpan.FromSeconds(10)));

            var  sut = new RetryDelegatingHandler(contextMock, innerHandlerMock);
            var  cancellationToken = new CancellationToken();
            Task firstOpen         = sut.OpenAsync(cancellationToken);
            Task secondOpen        = sut.OpenAsync(cancellationToken);

            tcs.SetResult(0);
            await Task.WhenAll(firstOpen, secondOpen).ConfigureAwait(false);

            Assert.AreEqual(1, callCounter);
        }
예제 #3
0
        public async Task RetrySetRetryPolicyVerifyInternalsSuccess()
        {
            var innerHandlerMock = Substitute.For <IDelegatingHandler>();
            var contextMock      = Substitute.For <IPipelineContext>();
            var sut = new RetryDelegatingHandler(contextMock, innerHandlerMock);

            var retryPolicy = new TestRetryPolicy();

            sut.SetRetryPolicy(retryPolicy);

            int innerHandlerCallCounter = 0;

            innerHandlerMock.OpenAsync(Arg.Any <CancellationToken>()).Returns(t =>
            {
                innerHandlerCallCounter++;
                throw new IotHubCommunicationException();
            });

            await sut.OpenAsync(CancellationToken.None).ExpectedAsync <IotHubCommunicationException>().ConfigureAwait(false);

            Assert.AreEqual(2, innerHandlerCallCounter);
            Assert.AreEqual(2, retryPolicy.Counter);

            var noretry = new NoRetry();

            sut.SetRetryPolicy(noretry);
            await sut.OpenAsync(CancellationToken.None).ExpectedAsync <IotHubCommunicationException>().ConfigureAwait(false);

            Assert.AreEqual(3, innerHandlerCallCounter);
            Assert.AreEqual(2, retryPolicy.Counter);
        }
        public async Task OpenAsyncInnerFailedSutIsOpenAndCanBeReopen()
        {
            var contextMock = Substitute.For <PipelineContext>();

            contextMock.ConnectionStatusChangesHandler = new ConnectionStatusChangesHandler(delegate(ConnectionStatus status, ConnectionStatusChangeReason reason) { });
            var  innerHandlerMock = Substitute.For <IDelegatingHandler>();
            bool shouldThrow      = true;

            innerHandlerMock.OpenAsync(Arg.Any <CancellationToken>()).Returns(ci =>
            {
                if (shouldThrow)
                {
                    throw new IOException();
                }
                else
                {
                    return(TaskHelpers.CompletedTask);;
                }
            });

            var sut = new RetryDelegatingHandler(contextMock, innerHandlerMock);
            var cancellationToken = new CancellationToken();
            await sut.OpenAsync(cancellationToken).ExpectedAsync <IOException>().ConfigureAwait(false);

            shouldThrow = false;

            await sut.OpenAsync(cancellationToken).ConfigureAwait(false);
        }
        public async Task RetryTransientErrorOccuredRetried()
        {
            int callCounter = 0;

            var contextMock      = Substitute.For <IPipelineContext>();
            var innerHandlerMock = Substitute.For <IDelegatingHandler>();

            innerHandlerMock.OpenAsync(Arg.Any <CancellationToken>()).Returns(t =>
            {
                callCounter++;

                if (callCounter == 1)
                {
                    throw new IotHubException("Test transient exception", isTransient: true);
                }
                return(Task.CompletedTask);
            });

            var sut = new RetryDelegatingHandler(contextMock, innerHandlerMock);

            var cancellationToken = new CancellationToken();
            await sut.OpenAsync(cancellationToken).ConfigureAwait(false);

            Assert.AreEqual(2, callCounter);
        }
예제 #6
0
        public async Task Retry_CloseAsyncSuccessDisposesHandler_Throws()
        {
            var contextMock       = Substitute.For <IPipelineContext>();
            var innerHandlerMock  = Substitute.For <IDelegatingHandler>();
            var cancellationToken = new CancellationToken();

            innerHandlerMock.OpenAsync(cancellationToken).Returns(t => TaskHelpers.CompletedTask);
            innerHandlerMock.CloseAsync(cancellationToken).Returns(t => TaskHelpers.CompletedTask);

            var sut = new RetryDelegatingHandler(contextMock, innerHandlerMock);
            await sut.OpenAsync(cancellationToken).ConfigureAwait(false);

            await sut.CloseAsync(cancellationToken).ConfigureAwait(false);

            await((Func <Task>)(() => sut.OpenAsync(cancellationToken))).ExpectedAsync <ObjectDisposedException>().ConfigureAwait(false);
        }
예제 #7
0
        public async Task Retry_NonTransientErrorThrown_Throws()
        {
            int callCounter = 0;

            var contextMock      = Substitute.For <IPipelineContext>();
            var innerHandlerMock = Substitute.For <IDelegatingHandler>();

            innerHandlerMock.OpenAsync(true, Arg.Any <CancellationToken>()).Returns(t =>
            {
                callCounter++;

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

            var sut = new RetryDelegatingHandler(contextMock);

            sut.ContinuationFactory = c => innerHandlerMock;
            var cancellationToken = new CancellationToken();
            await sut.OpenAsync(true, cancellationToken).ExpectedAsync <InvalidOperationException>();

            Assert.AreEqual(callCounter, 1);
        }
예제 #8
0
        public async Task Retry_TransientErrorOccured_Retried()
        {
            int callCounter = 0;

            var contextMock      = Substitute.For <IPipelineContext>();
            var innerHandlerMock = Substitute.For <IDelegatingHandler>();

            innerHandlerMock.OpenAsync(true, Arg.Any <CancellationToken>()).Returns(t =>
            {
                callCounter++;

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

            var sut = new RetryDelegatingHandler(contextMock);

            sut.ContinuationFactory = c => innerHandlerMock;

            var cancellationToken = new CancellationToken();
            await sut.OpenAsync(true, cancellationToken);

            Assert.AreEqual(2, callCounter);
        }
        public async Task DeviceNotFoundExceptionReturnsDeviceDisabledStatus()
        {
            // arrange
            var contextMock      = Substitute.For <PipelineContext>();
            var innerHandlerMock = Substitute.For <IDelegatingHandler>();

            innerHandlerMock.OpenAsync(Arg.Any <CancellationToken>()).Returns(t => throw new DeviceNotFoundException());

            ConnectionStatus?              status              = null;
            ConnectionStatusChangeReason?  statusChangeReason  = null;
            ConnectionStatusChangesHandler statusChangeHandler = (s, r) =>
            {
                status             = s;
                statusChangeReason = r;
            };

            contextMock.ConnectionStatusChangesHandler = statusChangeHandler;

            var sut = new RetryDelegatingHandler(contextMock, innerHandlerMock);

            // act
            await((Func <Task>)(() => sut
                                .OpenAsync(CancellationToken.None)))
            .ExpectedAsync <DeviceNotFoundException>()
            .ConfigureAwait(false);

            // assert
            status.Should().Be(ConnectionStatus.Disconnected);
            statusChangeReason.Should().Be(ConnectionStatusChangeReason.Device_Disabled);
        }
예제 #10
0
        public async Task DeviceNotFoundExceptionReturnsDeviceDisabledStatus()
        {
            var contextMock      = Substitute.For <IPipelineContext>();
            var innerHandlerMock = Substitute.For <IDelegatingHandler>();

            innerHandlerMock.OpenAsync(Arg.Any <CancellationToken>()).Returns(t => throw new DeviceNotFoundException());

            ConnectionStatus?              status              = null;
            ConnectionStatusChangeReason?  statusChangeReason  = null;
            ConnectionStatusChangesHandler statusChangeHandler = (s, r) =>
            {
                status             = s;
                statusChangeReason = r;
            };

            contextMock.Get <ConnectionStatusChangesHandler>().Returns(statusChangeHandler);

            var cancellationToken = new CancellationToken();
            var testee            = new RetryDelegatingHandler(contextMock, innerHandlerMock);

            await((Func <Task>)(() => testee.OpenAsync(cancellationToken))).ExpectedAsync <DeviceNotFoundException>().ConfigureAwait(false);

            Assert.AreEqual(ConnectionStatus.Disconnected, status);
            Assert.AreEqual(ConnectionStatusChangeReason.Device_Disabled, statusChangeReason);
        }
        public async Task RetryNonTransientErrorThrownThrows()
        {
            // arrange
            int callCounter = 0;

            var contextMock = Substitute.For <PipelineContext>();

            contextMock.ConnectionStatusChangesHandler = new ConnectionStatusChangesHandler(delegate(ConnectionStatus status, ConnectionStatusChangeReason reason) { });
            var innerHandlerMock = Substitute.For <IDelegatingHandler>();

            innerHandlerMock
            .OpenAsync(Arg.Any <CancellationToken>())
            .Returns(t =>
            {
                if (++callCounter == 1)
                {
                    throw new InvalidOperationException("");
                }
                return(TaskHelpers.CompletedTask);
            });

            var sut = new RetryDelegatingHandler(contextMock, innerHandlerMock);

            // arrange
            await sut.OpenAsync(CancellationToken.None).ExpectedAsync <InvalidOperationException>().ConfigureAwait(false);

            // act
            callCounter.Should().Be(1);
        }
        public async Task RetryDelegatingHandler_OpenAsyncRetries()
        {
            // arrange
            int callCounter = 0;

            var             ct          = CancellationToken.None;
            PipelineContext contextMock = Substitute.For <PipelineContext>();

            contextMock.ConnectionStatusChangesHandler = new ConnectionStatusChangesHandler(delegate(ConnectionStatus status, ConnectionStatusChangeReason reason) { });
            IDelegatingHandler innerHandlerMock = Substitute.For <IDelegatingHandler>();

            innerHandlerMock
            .OpenAsync(ct)
            .Returns(t =>
            {
                return(++callCounter == 1
                            ? throw new IotHubException("Test transient exception", isTransient: true)
                            : TaskHelpers.CompletedTask);
            });
            innerHandlerMock.WaitForTransportClosedAsync().Returns(Task.Delay(TimeSpan.FromSeconds(10)));

            var retryDelegatingHandler = new RetryDelegatingHandler(contextMock, innerHandlerMock);

            // act
            await retryDelegatingHandler.OpenAsync(ct).ConfigureAwait(false);

            // assert
            callCounter.Should().Be(2);
        }
        public async Task OpenAsyncInnerCancelledSutIsOpenAndCanBeReopen()
        {
            var contextMock = Substitute.For <IPipelineContext>();
            var tcs         = new TaskCompletionSource();

            tcs.SetCanceled();
            var innerHandlerMock = Substitute.For <IDelegatingHandler>();

            innerHandlerMock.OpenAsync(Arg.Any <CancellationToken>()).Returns(tcs.Task);

            var sut = new RetryDelegatingHandler(contextMock, innerHandlerMock);
            var cancellationToken = new CancellationToken();
            await sut.OpenAsync(cancellationToken).ExpectedAsync <TaskCanceledException>().ConfigureAwait(false);

            innerHandlerMock.OpenAsync(Arg.Any <CancellationToken>()).Returns(t => Task.CompletedTask);

            await sut.OpenAsync(cancellationToken).ConfigureAwait(false);
        }
        public async Task OpenAsyncInnerCompletedSubjIsOpen()
        {
            var contextMock      = Substitute.For <IPipelineContext>();
            var innerHandlerMock = Substitute.For <IDelegatingHandler>();

            innerHandlerMock.OpenAsync(Arg.Any <CancellationToken>()).Returns(t => Task.CompletedTask);

            var cancellationToken = new CancellationToken();
            var sut = new RetryDelegatingHandler(contextMock, innerHandlerMock);
            await sut.OpenAsync(cancellationToken).ConfigureAwait(false);
        }
예제 #15
0
        public async Task Retry_CancellationTokenCanceled_Open()
        {
            var innerHandlerMock = Substitute.For <IDelegatingHandler>();

            innerHandlerMock.OpenAsync(Arg.Any <bool>(), Arg.Any <CancellationToken>()).Returns(TaskConstants.Completed);

            var sut = new RetryDelegatingHandler(innerHandlerMock);
            var cancellationTokenSource = new CancellationTokenSource();

            cancellationTokenSource.Cancel();
            await sut.OpenAsync(Arg.Any <bool>(), cancellationTokenSource.Token).ExpectedAsync <TaskCanceledException>();
        }
        public async Task OpenAsyncInnerCompletedSubjIsOpen()
        {
            var contextMock = Substitute.For <PipelineContext>();

            contextMock.ConnectionStatusChangesHandler = new ConnectionStatusChangesHandler(delegate(ConnectionStatus status, ConnectionStatusChangeReason reason) { });
            var innerHandlerMock = Substitute.For <IDelegatingHandler>();

            innerHandlerMock.OpenAsync(Arg.Any <CancellationToken>()).Returns(t => TaskHelpers.CompletedTask);

            var cancellationToken = new CancellationToken();
            var sut = new RetryDelegatingHandler(contextMock, innerHandlerMock);
            await sut.OpenAsync(cancellationToken).ConfigureAwait(false);
        }
        public async Task RetryCancellationTokenCanceledOpen()
        {
            var innerHandlerMock        = Substitute.For <IDelegatingHandler>();
            var cancellationTokenSource = new CancellationTokenSource();

            cancellationTokenSource.Cancel();
            innerHandlerMock.OpenAsync(Arg.Any <CancellationToken>()).Returns(TaskHelpers.CompletedTask);

            var contextMock = Substitute.For <IPipelineContext>();
            var sut         = new RetryDelegatingHandler(contextMock, innerHandlerMock);

            await sut.OpenAsync(cancellationTokenSource.Token).ExpectedAsync <TaskCanceledException>().ConfigureAwait(false);
        }
예제 #18
0
        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 OpenAsyncTwoCallersOnlyOneOpenCalled()
        {
            var contextMock      = Substitute.For <IPipelineContext>();
            var tcs              = new TaskCompletionSource();
            var innerHandlerMock = Substitute.For <IDelegatingHandler>();
            int callCounter      = 0;

            innerHandlerMock.OpenAsync(Arg.Any <CancellationToken>()).Returns(t =>
            {
                callCounter++;
                return(tcs.Task);
            });

            var  sut = new RetryDelegatingHandler(contextMock, innerHandlerMock);
            var  cancellationToken = new CancellationToken();
            Task firstOpen         = sut.OpenAsync(cancellationToken);
            Task secondOpen        = sut.OpenAsync(cancellationToken);

            tcs.Complete();
            await Task.WhenAll(firstOpen, secondOpen).ConfigureAwait(false);

            Assert.AreEqual(1, callCounter);
        }
        public async Task RetryCancellationTokenCanceledOpen()
        {
            var innerHandlerMock        = Substitute.For <IDelegatingHandler>();
            var cancellationTokenSource = new CancellationTokenSource();

            cancellationTokenSource.Cancel();
            innerHandlerMock.OpenAsync(Arg.Any <bool>(), Arg.Any <CancellationToken>()).Returns(TaskConstants.Completed);

            var contextMock = Substitute.For <IPipelineContext>();
            var sut         = new RetryDelegatingHandler(contextMock);

            sut.ContinuationFactory = c => innerHandlerMock;

            await sut.OpenAsync(true, cancellationTokenSource.Token).ExpectedAsync <TaskCanceledException>().ConfigureAwait(false);
        }
예제 #21
0
        public async Task Retry_TransientErrorThrownAfterNumberOfRetries_Throws()
        {
            var contextMock      = Substitute.For <IPipelineContext>();
            var innerHandlerMock = Substitute.For <IDelegatingHandler>();

            innerHandlerMock.OpenAsync(Arg.Is(true), Arg.Any <CancellationToken>()).Returns(t =>
            {
                throw new IotHubClientTransientException("");
            });

            var sut = new RetryDelegatingHandler(contextMock);

            sut.ContinuationFactory = c => innerHandlerMock;
            var cancellationToken = new CancellationToken();
            await sut.OpenAsync(true, cancellationToken).ExpectedAsync <IotHubClientTransientException>();
        }
예제 #22
0
        public async Task RetryTransientErrorThrownAfterNumberOfRetriesThrows()
        {
            var contextMock      = Substitute.For <IPipelineContext>();
            var innerHandlerMock = Substitute.For <IDelegatingHandler>();

            innerHandlerMock.OpenAsync(Arg.Any <CancellationToken>()).Returns(t =>
            {
                throw new IotHubException(TestExceptionMessage, isTransient: true);
            });

            var sut = new RetryDelegatingHandler(contextMock, innerHandlerMock);

            using (var cts = new CancellationTokenSource(100))
            {
                IotHubException exception = await sut.OpenAsync(cts.Token).ExpectedAsync <IotHubException>().ConfigureAwait(false);

                Assert.AreEqual(TestExceptionMessage, exception.Message);
            }
        }
예제 #23
0
        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);
        }
예제 #24
0
        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);
        }
예제 #25
0
        public async Task RetryNonTransientErrorThrownThrows()
        {
            int callCounter = 0;

            var contextMock      = Substitute.For <IPipelineContext>();
            var innerHandlerMock = Substitute.For <IDelegatingHandler>();

            innerHandlerMock.OpenAsync(Arg.Any <CancellationToken>()).Returns(t =>
            {
                callCounter++;

                if (callCounter == 1)
                {
                    throw new InvalidOperationException("");
                }
                return(TaskHelpers.CompletedTask);;
            });

            var sut = new RetryDelegatingHandler(contextMock, innerHandlerMock);
            var cancellationToken = new CancellationToken();
            await sut.OpenAsync(cancellationToken).ExpectedAsync <InvalidOperationException>().ConfigureAwait(false);

            Assert.AreEqual(callCounter, 1);
        }
예제 #26
0
        public async Task RetryDelegatingHandler_OpenAsyncRetries()
        {
            // arrange
            int callCounter = 0;

            IPipelineContext   contextMock      = Substitute.For <IPipelineContext>();
            IDelegatingHandler innerHandlerMock = Substitute.For <IDelegatingHandler>();

            innerHandlerMock.OpenAsync(Arg.Any <CancellationToken>()).Returns(t =>
            {
                return(++callCounter == 1
                    ? throw new IotHubException("Test transient exception", isTransient: true)
                    : TaskHelpers.CompletedTask);
            });
            innerHandlerMock.WaitForTransportClosedAsync().Returns(Task.Delay(TimeSpan.FromSeconds(10)));

            var retryDelegatingHandler = new RetryDelegatingHandler(contextMock, innerHandlerMock);

            // act
            await retryDelegatingHandler.OpenAsync(new CancellationToken()).ConfigureAwait(false);

            // assert
            Assert.AreEqual(2, callCounter);
        }
        public async Task RetryTransientErrorThrownAfterNumberOfRetriesThrows()
        {
            // arrange
            using var cts = new CancellationTokenSource(100);
            var contextMock = Substitute.For <PipelineContext>();

            contextMock.ConnectionStatusChangesHandler = new ConnectionStatusChangesHandler(delegate(ConnectionStatus status, ConnectionStatusChangeReason reason) { });
            var innerHandlerMock = Substitute.For <IDelegatingHandler>();

            innerHandlerMock
            .OpenAsync(cts.Token)
            .Returns(t => throw new IotHubException(TestExceptionMessage, isTransient: true));

            var             sut       = new RetryDelegatingHandler(contextMock, innerHandlerMock);
            IotHubException exception = await sut
                                        .OpenAsync(cts.Token)
                                        .ExpectedAsync <IotHubException>()
                                        .ConfigureAwait(false);

            // act

            // assert
            exception.Message.Should().Be(TestExceptionMessage);
        }