public async Task Enqueue_ShouldQueue_PendingTask() { // Arrange const int expected1 = 291; const int expected2 = 872; using (var breakpoint = new Breakpoint()) { var queue = new CoalescingTaskQueue <int, int>((newArg, arg, running) => CoalesceDecision.None); async Task <int> TestAction(int result) { // ReSharper disable once AccessToDisposedClosure await breakpoint.Hit().WaitForContinue(); return(result); } // Act var task1 = queue.Enqueue(() => TestAction(expected1), expected1); var task2 = queue.Enqueue(() => TestAction(expected2), expected2); await breakpoint.WaitForHitAndContinue().TimeoutAfter(TestTimeout); await breakpoint.WaitForHitAndContinue().TimeoutAfter(TestTimeout); // Assert task1.Result.Should().Be(expected1); task2.Result.Should().Be(expected2); } }
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 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); } }
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 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(); }