Exemple #1
0
        public async Task Cancel_ShouldCancel_PendingAndRunningTasks()
        {
            // Arrange
            using (var breakpoint = new Breakpoint())
            {
                var queue = new CoalescingTaskQueue <int, int>((newArg, arg, running) =>
                                                               CoalesceDecision.None);

                async Task <int> TestAction(int result, CancellationToken ct)
                {
                    // ReSharper disable once AccessToDisposedClosure
                    await breakpoint.Hit().WaitForContinue();

                    ct.ThrowIfCancellationRequested();
                    return(result);
                }

                // Act
                var task1 = queue.Enqueue(ct => TestAction(6517, ct), 6517);
                var hit1  = await breakpoint.WaitForHit().TimeoutAfter(TestTimeout);

                var task2 = queue.Enqueue(ct => TestAction(101, ct), 101);

                queue.Cancel();

                hit1.Continue();
                await Task.WhenAny(task1);

                // Assert
                task1.IsCanceled.Should().BeTrue();
                task2.IsCanceled.Should().BeTrue();
            }
        }
Exemple #2
0
        public async Task Enqueue_ShouldJoin_RunningTask()
        {
            // Arrange
            const int expected = 147;

            using (var breakpoint = new Breakpoint())
            {
                var queue = new CoalescingTaskQueue <int, int>((newArg, arg, running) => CoalesceDecision.Join);

                async Task <int> TestAction(int result)
                {
                    // ReSharper disable once AccessToDisposedClosure
                    await breakpoint.Hit().WaitForContinue();

                    return(result);
                }

                // Act
                var task1 = queue.Enqueue(() => TestAction(expected), expected);
                var hit1  = await breakpoint.WaitForHit().TimeoutAfter(TestTimeout);

                var task2 = queue.Enqueue(() => TestAction(328), 328);

                hit1.Continue();

                // Assert
                task1.Result.Should().Be(expected);
                task2.Result.Should().Be(expected);
            }
        }
Exemple #3
0
        public async Task Enqueue_ShouldCancel_PendingAndRunningTasks()
        {
            // Arrange
            const int expected3 = 3617;

            using (var breakpoint = new Breakpoint())
            {
                var queue = new CoalescingTaskQueue <int, int>((newArg, arg, running) =>
                                                               newArg == expected3 ? CoalesceDecision.Cancel : CoalesceDecision.None);

                async Task <int> TestAction(int result, CancellationToken ct)
                {
                    // ReSharper disable once AccessToDisposedClosure
                    await breakpoint.Hit().WaitForContinue();

                    ct.ThrowIfCancellationRequested();
                    return(result);
                }

                // Act
                var task1 = queue.Enqueue(ct => TestAction(202, ct), 202);
                var hit1  = await breakpoint.WaitForHit().TimeoutAfter(TestTimeout);

                var task2 = queue.Enqueue(ct => TestAction(303, ct), 303);
                var task3 = queue.Enqueue(ct => TestAction(expected3, ct), expected3);
                hit1.Continue();
                await breakpoint.WaitForHitAndContinue().TimeoutAfter(TestTimeout);

                // Assert
                task1.IsCanceled.Should().BeTrue();
                task2.IsCanceled.Should().BeTrue();
                task3.Result.Should().Be(expected3);
            }
        }
Exemple #4
0
        public async Task Enqueue_ShouldNotJoin_CancelledRunningTask()
        {
            // Arrange
            const int expected = 6874;

            using (var breakpoint = new Breakpoint())
            {
                var queue = new CoalescingTaskQueue <int, int>((newArg, arg, running) =>
                                                               CoalesceDecision.Join);

                async Task <int> TestAction(int result, CancellationToken ct)
                {
                    // ReSharper disable once AccessToDisposedClosure
                    await breakpoint.Hit().WaitForContinue();

                    ct.ThrowIfCancellationRequested();
                    return(result);
                }

                // Act
                _ = queue.Enqueue(ct => TestAction(1981, ct), 1981);
                var hit1 = await breakpoint.WaitForHit().TimeoutAfter(TestTimeout);

                queue.Cancel();
                var task2 = queue.Enqueue(ct => TestAction(expected, ct), expected);
                hit1.Continue();
                await breakpoint.WaitForHitAndContinue().TimeoutAfter(TestTimeout);

                // Assert
                task2.Result.Should().Be(expected);
            }
        }
        public async Task TimeoutAfter_ShouldThrow_TimeoutException_WhenActionTimedOut()
        {
            // Arrange
            var breakpoint = new Breakpoint();

            async Task Action(CancellationToken ct)
            {
                await breakpoint.Hit().WaitForContinue();

                ct.ThrowIfCancellationRequested();
            }

            // Act
            var task = TaskExtensions.TimeoutAfter(Action, TimeSpan.Zero, CancellationToken.None);
            var hit  = await breakpoint.WaitForHit().TimeoutAfter(TestTimeout);

            await Task.Delay(TimeSpan.FromMilliseconds(100));

            hit.Continue();

            Func <Task> action = async() => await task;

            // Assert
            await action.Should().ThrowAsync <TimeoutException>();
        }
Exemple #6
0
        public async Task ExecuteAsync_ShouldCancelAction_WhenCancellationToken_IsCancelled()
        {
            // Arrange
            var policy = new ServiceRetryPolicy(0, TimeSpan.Zero);

            using (var cancellationSource = new CancellationTokenSource())
                using (var breakpoint = new Breakpoint())
                {
                    var cancelled = false;

                    // Act
                    var task = policy.ExecuteAsync(
                        async ct =>
                    {
                        // ReSharper disable once AccessToDisposedClosure
                        await breakpoint.Hit().WaitForContinue();
                        cancelled = ct.IsCancellationRequested;
                        ct.ThrowIfCancellationRequested();
                        return(Result.Ok());
                    },
                        cancellationSource.Token);

                    var hit = await breakpoint.WaitForHit().TimeoutAfter(TestTimeout);

                    cancellationSource.Cancel();
                    hit.Continue();
                    var result = await task.TimeoutAfter(TestTimeout);

                    // Assert
                    result.Success.Should().BeFalse();
                    cancelled.Should().BeTrue();
                }
        }
Exemple #7
0
        public async Task Enqueue_ShouldJoin_PendingTask()
        {
            // Arrange
            const int expected1 = 3905;
            const int expected2 = 4487;

            using (var breakpoint = new Breakpoint())
            {
                var queue = new CoalescingTaskQueue <int, int>((newArg, arg, running) =>
                                                               newArg > 0 ? CoalesceDecision.None : CoalesceDecision.Join);

                async Task <int> TestAction(int result, CancellationToken ct)
                {
                    // ReSharper disable once AccessToDisposedClosure
                    await breakpoint.Hit().WaitForContinue();

                    ct.ThrowIfCancellationRequested();
                    return(result);
                }

                // Act
                var task1 = queue.Enqueue(ct => TestAction(expected1, ct), expected1);
                var hit1  = await breakpoint.WaitForHit().TimeoutAfter(TestTimeout);

                var task2 = queue.Enqueue(ct => TestAction(expected2, ct), expected2);

                var task3 = queue.Enqueue(ct => TestAction(-15, ct), -15);

                hit1.Continue();
                await breakpoint.WaitForHitAndContinue().TimeoutAfter(TestTimeout);

                // Assert
                task1.Result.Should().Be(expected1);
                task2.Result.Should().Be(expected2);
                task3.Result.Should().Be(expected2);
            }
        }
        public async Task TimeoutAfter_ShouldThrow_TaskCanceledException_WhenActionCancelled()
        {
            // Arrange
            var breakpoint         = new Breakpoint();
            var cancellationSource = new CancellationTokenSource();

            async Task Action(CancellationToken ct)
            {
                await breakpoint.Hit().WaitForContinue();

                ct.ThrowIfCancellationRequested();
            }

            // Act
            var task = TaskExtensions.TimeoutAfter(Action, TimeSpan.Zero, cancellationSource.Token);
            var hit  = await breakpoint.WaitForHit().TimeoutAfter(TestTimeout);

            cancellationSource.Cancel();
            hit.Continue();
            Func <Task> action = async() => await task.TimeoutAfter(TestTimeout);

            // Assert
            await action.Should().ThrowAsync <OperationCanceledException>();
        }
        public async Task SendAsync_ShouldRetryWithNewToken_WhenRefreshedWhileRequesting()
        {
            // Arrange
            BreakpointHandler breakpointHandler = new BreakpointHandler {
                InnerHandler = _innerHandler
            };
            Breakpoint                  requestBreakpoint     = breakpointHandler.Breakpoint;
            BreakpointTokenClient       breakpointTokenClient = new BreakpointTokenClient(_tokenClient);
            Breakpoint                  tokenClientBreakpoint = breakpointTokenClient.Breakpoint;
            UnauthorizedResponseHandler handler = new UnauthorizedResponseHandler(breakpointTokenClient, _tokenStorage, _userStorage, _logger)
            {
                InnerHandler = breakpointHandler
            };
            HttpClient client = new HttpClient(handler)
            {
                BaseAddress = _baseAddress
            };

            _tokenClient.RefreshTokenAsync(Arg.Any <CancellationToken>())
            .Returns(ApiResponseResult <RefreshTokenResponse> .Ok(
                         new RefreshTokenResponse {
                AccessToken = "New access token", RefreshToken = "New refresh token"
            }));

            HttpResponseMessage response = new HttpResponseMessage(HttpStatusCode.OK);

            // Act
            Task task1 = Task.CompletedTask;
            Task task2 = Task.CompletedTask;

            try
            {
                // Sending first request and pausing it
                HttpRequestMessage request1 = new HttpRequestMessage(HttpMethod.Get, "/vpn");
                task1 = client.SendAsync(request1);
                BreakpointHit request1Hit = await requestBreakpoint.WaitForHit().TimeoutAfter(TestTimeout);

                // Sending second request and pausing it
                HttpRequestMessage request2 = new HttpRequestMessage(HttpMethod.Get, "/profiles");
                task2 = client.SendAsync(request2);
                BreakpointHit request2Hit = await requestBreakpoint.WaitForHit().TimeoutAfter(TestTimeout);

                // Continue first request and get Unauthorized
                _innerHandler.Expect(HttpMethod.Get, "https://api.protonvpn.ch/vpn")
                .Respond(HttpStatusCode.Unauthorized);
                request1Hit.Continue();

                // First request initiated token refresh
                await tokenClientBreakpoint.WaitForHitAndContinue().TimeoutAfter(TestTimeout);

                // First request retried with new tokens
                request1Hit = await requestBreakpoint.WaitForHit().TimeoutAfter(TestTimeout);

                _innerHandler.Expect(HttpMethod.Get, "https://api.protonvpn.ch/vpn")
                .WithHeaders("Authorization", "Bearer New access token")
                .Respond(req => response);
                request1Hit.Continue();
                await task1.TimeoutAfter(TestTimeout);

                // Second request continues and gets Unauthorized
                _innerHandler.Expect(HttpMethod.Get, "https://api.protonvpn.ch/profiles")
                .Respond(HttpStatusCode.Unauthorized);
                request2Hit.Continue();

                // Second request retried with new access token
                request2Hit = await requestBreakpoint.WaitForHit().TimeoutAfter(TestTimeout);

                _innerHandler.Expect(HttpMethod.Get, "https://api.protonvpn.ch/profiles")
                .WithHeaders("Authorization", "Bearer New access token")
                .Respond(req => response);
                request2Hit.Continue();
            }
            finally
            {
                await task1.TimeoutAfter(TestTimeout);

                await task2.TimeoutAfter(TestTimeout);
            }

            // Assert
            await _tokenClient.Received(1).RefreshTokenAsync(Arg.Any <CancellationToken>());

            _innerHandler.VerifyNoOutstandingExpectation();
        }