From d6395a52bc2de85d9513cb45cba3d9113c4d2a60 Mon Sep 17 00:00:00 2001 From: David Fowler Date: Sat, 14 Apr 2018 04:45:16 -0700 Subject: [PATCH] Send delete request after poll ends (#2020) * Added test and fixed other test --- .../Internal/LongPollingTransport.cs | 8 +-- .../LongPollingTransportTests.cs | 54 ++++++++++++++++++- 2 files changed, 57 insertions(+), 5 deletions(-) diff --git a/src/Microsoft.AspNetCore.Http.Connections.Client/Internal/LongPollingTransport.cs b/src/Microsoft.AspNetCore.Http.Connections.Client/Internal/LongPollingTransport.cs index 3415335068..30be6d696b 100644 --- a/src/Microsoft.AspNetCore.Http.Connections.Client/Internal/LongPollingTransport.cs +++ b/src/Microsoft.AspNetCore.Http.Connections.Client/Internal/LongPollingTransport.cs @@ -88,16 +88,16 @@ namespace Microsoft.AspNetCore.Http.Connections.Client.Internal // Set the sending error so we communicate that to the application _error = sending.IsFaulted ? sending.Exception.InnerException : null; - // Send the DELETE request to clean-up the connection on the server. - // This will also cause the poll to return. - await SendDeleteRequest(url); - + // Cancel the poll request _transportCts.Cancel(); // Cancel any pending flush so that we can quit _application.Output.CancelPendingFlush(); await receiving; + + // Send the DELETE request to clean-up the connection on the server. + await SendDeleteRequest(url); } } diff --git a/test/Microsoft.AspNetCore.SignalR.Client.Tests/LongPollingTransportTests.cs b/test/Microsoft.AspNetCore.SignalR.Client.Tests/LongPollingTransportTests.cs index 1d2c378076..5e203256f0 100644 --- a/test/Microsoft.AspNetCore.SignalR.Client.Tests/LongPollingTransportTests.cs +++ b/test/Microsoft.AspNetCore.SignalR.Client.Tests/LongPollingTransportTests.cs @@ -380,12 +380,13 @@ namespace Microsoft.AspNetCore.SignalR.Client.Tests } else if (request.Method == HttpMethod.Get) { + cancellationToken.Register(() => tcs.TrySetCanceled(cancellationToken)); // This is the poll task return await tcs.Task; } else if (request.Method == HttpMethod.Delete) { - tcs.TrySetResult(ResponseUtils.CreateResponse(HttpStatusCode.NoContent)); + return ResponseUtils.CreateResponse(HttpStatusCode.Accepted); } return ResponseUtils.CreateResponse(HttpStatusCode.OK); }); @@ -419,6 +420,57 @@ namespace Microsoft.AspNetCore.SignalR.Client.Tests } } + [Fact] + public async Task LongPollingTransportSendsDeleteAfterPollEnds() + { + var sentRequests = new List(); + var pollTcs = new TaskCompletionSource(); + var deleteTcs = new TaskCompletionSource(); + + var mockHttpHandler = new Mock(); + mockHttpHandler.Protected() + .Setup>("SendAsync", ItExpr.IsAny(), ItExpr.IsAny()) + .Returns(async (request, cancellationToken) => + { + await Task.Yield(); + if (request.Method == HttpMethod.Post) + { + // Build a new request object, but convert the entire payload to string + sentRequests.Add(await request.Content.ReadAsByteArrayAsync()); + } + else if (request.Method == HttpMethod.Get) + { + cancellationToken.Register(() => pollTcs.TrySetCanceled(cancellationToken)); + // This is the poll task + return await pollTcs.Task; + } + else if (request.Method == HttpMethod.Delete) + { + // The poll task should have been completed + Assert.True(pollTcs.Task.IsCompleted); + + deleteTcs.TrySetResult(null); + + return ResponseUtils.CreateResponse(HttpStatusCode.Accepted); + } + return ResponseUtils.CreateResponse(HttpStatusCode.OK); + }); + + using (var httpClient = new HttpClient(mockHttpHandler.Object)) + { + var longPollingTransport = new LongPollingTransport(httpClient); + + // Start the transport + await longPollingTransport.StartAsync(TestUri, TransferFormat.Binary); + + var task = longPollingTransport.StopAsync(); + + await deleteTcs.Task.OrTimeout(); + + await task.OrTimeout(); + } + } + [Theory] [InlineData(TransferFormat.Binary)] [InlineData(TransferFormat.Text)]