Exemple #1
0
        public async Task StopTransportWhenConnectionAlreadyStoppedOnServer()
        {
            var pollRequestTcs = new TaskCompletionSource <object>();

            var mockHttpHandler = new Mock <HttpMessageHandler>();
            var firstPoll       = true;

            mockHttpHandler.Protected()
            .Setup <Task <HttpResponseMessage> >("SendAsync", ItExpr.IsAny <HttpRequestMessage>(), ItExpr.IsAny <CancellationToken>())
            .Returns <HttpRequestMessage, CancellationToken>(async(request, cancellationToken) =>
            {
                await Task.Yield();
                if (request.Method == HttpMethod.Delete)
                {
                    // Simulate the server having already cleaned up the connection on the server
                    return(ResponseUtils.CreateResponse(HttpStatusCode.NotFound));
                }
                else
                {
                    if (firstPoll)
                    {
                        firstPoll = false;
                        return(ResponseUtils.CreateResponse(HttpStatusCode.OK));
                    }

                    await pollRequestTcs.Task;
                    return(ResponseUtils.CreateResponse(HttpStatusCode.OK));
                }
            });

            using (StartVerifiableLog())
            {
                using (var httpClient = new HttpClient(mockHttpHandler.Object))
                {
                    var longPollingTransport = new LongPollingTransport(httpClient, LoggerFactory);

                    await longPollingTransport.StartAsync(TestUri, TransferFormat.Binary).OrTimeout();

                    var stopTask = longPollingTransport.StopAsync();

                    pollRequestTcs.SetResult(null);

                    await stopTask.OrTimeout();
                }
            }
        }
        public async Task SendsDeleteRequestWhenTransportCompleted()
        {
            var handler = TestHttpMessageHandler.CreateDefault();

            using (var httpClient = new HttpClient(handler))
            {
                var longPollingTransport = new LongPollingTransport(httpClient);

                await longPollingTransport.StartAsync(TestUri, TransferFormat.Binary);

                await longPollingTransport.StopAsync();

                var deleteRequest = handler.ReceivedRequests.SingleOrDefault(r => r.Method == HttpMethod.Delete);
                Assert.NotNull(deleteRequest);
                Assert.Equal(TestUri, deleteRequest.RequestUri);
            }
        }
        public async Task LongPollingTransportRePollsIfRequestCanceled()
        {
            var numPolls      = 0;
            var completionTcs = new TaskCompletionSource <object>();

            var mockHttpHandler = new Mock <HttpMessageHandler>();

            mockHttpHandler.Protected()
            .Setup <Task <HttpResponseMessage> >("SendAsync", ItExpr.IsAny <HttpRequestMessage>(), ItExpr.IsAny <CancellationToken>())
            .Returns <HttpRequestMessage, CancellationToken>(async(request, cancellationToken) =>
            {
                await Task.Yield();

                if (numPolls == 0)
                {
                    numPolls++;
                    return(ResponseUtils.CreateResponse(HttpStatusCode.OK));
                }

                if (numPolls++ < 3)
                {
                    throw new OperationCanceledException();
                }

                completionTcs.SetResult(null);
                return(ResponseUtils.CreateResponse(HttpStatusCode.OK));
            });

            using (var httpClient = new HttpClient(mockHttpHandler.Object))
            {
                var longPollingTransport = new LongPollingTransport(httpClient);

                try
                {
                    await longPollingTransport.StartAsync(TestUri, TransferFormat.Binary);

                    var completedTask = await Task.WhenAny(completionTcs.Task, longPollingTransport.Running).OrTimeout();

                    Assert.Equal(completionTcs.Task, completedTask);
                }
                finally
                {
                    await longPollingTransport.StopAsync();
                }
            }
        }
Exemple #4
0
        public async Task LongPollingTransportSendsAvailableMessagesWhenTheyArrive()
        {
            var sentRequests = new List <byte[]>();

            var mockHttpHandler = new Mock <HttpMessageHandler>();

            mockHttpHandler.Protected()
            .Setup <Task <HttpResponseMessage> >("SendAsync", ItExpr.IsAny <HttpRequestMessage>(), ItExpr.IsAny <CancellationToken>())
            .Returns <HttpRequestMessage, CancellationToken>(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());
                }
                return(ResponseUtils.CreateResponse(HttpStatusCode.OK));
            });

            using (var httpClient = new HttpClient(mockHttpHandler.Object))
            {
                var longPollingTransport = new LongPollingTransport(httpClient);
                try
                {
                    // Start the transport
                    await longPollingTransport.StartAsync(new Uri("http://fakeuri.org"), TransferFormat.Binary);

                    longPollingTransport.Output.Write(Encoding.UTF8.GetBytes("Hello"));
                    longPollingTransport.Output.Write(Encoding.UTF8.GetBytes("World"));
                    await longPollingTransport.Output.FlushAsync();

                    longPollingTransport.Output.Complete();

                    await longPollingTransport.Running.OrTimeout();

                    await longPollingTransport.Input.ReadAllAsync();

                    Assert.Single(sentRequests);
                    Assert.Equal(new[] { (byte)'H', (byte)'e', (byte)'l', (byte)'l', (byte)'o', (byte)'W', (byte)'o', (byte)'r', (byte)'l', (byte)'d' }, sentRequests[0]);
                }
                finally
                {
                    await longPollingTransport.StopAsync();
                }
            }
        }
    public async Task LongPollingTransportStopsWhenPollRequestFails()
    {
        var mockHttpHandler = new Mock <HttpMessageHandler>();
        var firstPoll       = true;

        mockHttpHandler.Protected()
        .Setup <Task <HttpResponseMessage> >("SendAsync", ItExpr.IsAny <HttpRequestMessage>(), ItExpr.IsAny <CancellationToken>())
        .Returns <HttpRequestMessage, CancellationToken>(async(request, cancellationToken) =>
        {
            await Task.Yield();
            if (firstPoll)
            {
                firstPoll = false;
                return(ResponseUtils.CreateResponse(HttpStatusCode.OK));
            }
            return(ResponseUtils.CreateResponse(HttpStatusCode.InternalServerError));
        });

        using (var httpClient = new HttpClient(mockHttpHandler.Object))
        {
            var longPollingTransport = new LongPollingTransport(httpClient);
            try
            {
                await longPollingTransport.StartAsync(TestUri, TransferFormat.Binary);

                var exception =
                    await Assert.ThrowsAsync <HttpRequestException>(async() =>
                {
                    async Task ReadAsync()
                    {
                        await longPollingTransport.Input.ReadAsync();
                    }

                    await ReadAsync().DefaultTimeout();
                });

                Assert.Contains(" 500 ", exception.Message);
            }
            finally
            {
                await longPollingTransport.StopAsync();
            }
        }
    }
Exemple #6
0
        public async Task LongPollingTransportStopsWhenSendRequestFails()
        {
            var mockHttpHandler = new Mock <HttpMessageHandler>();

            mockHttpHandler.Protected()
            .Setup <Task <HttpResponseMessage> >("SendAsync", ItExpr.IsAny <HttpRequestMessage>(), ItExpr.IsAny <CancellationToken>())
            .Returns <HttpRequestMessage, CancellationToken>(async(request, cancellationToken) =>
            {
                await Task.Yield();
                var statusCode = request.Method == HttpMethod.Post
                        ? HttpStatusCode.InternalServerError
                        : HttpStatusCode.OK;
                return(ResponseUtils.CreateResponse(statusCode));
            });

            using (var httpClient = new HttpClient(mockHttpHandler.Object))
            {
                var longPollingTransport = new LongPollingTransport(httpClient);
                try
                {
                    var connectionToTransport = Channel.CreateUnbounded <SendMessage>();
                    var transportToConnection = Channel.CreateUnbounded <byte[]>();
                    var channelConnection     = new ChannelConnection <SendMessage, byte[]>(connectionToTransport, transportToConnection);
                    await longPollingTransport.StartAsync(new Uri("http://fakeuri.org"), channelConnection, TransferMode.Binary, connectionId : string.Empty, connection : new TestConnection());

                    await connectionToTransport.Writer.WriteAsync(new SendMessage());

                    await Assert.ThrowsAsync <HttpRequestException>(async() => await longPollingTransport.Running.OrTimeout());

                    // The channel needs to be drained for the Completion task to be completed
                    while (transportToConnection.Reader.TryRead(out var message))
                    {
                    }

                    var exception = await Assert.ThrowsAsync <HttpRequestException>(async() => await transportToConnection.Reader.Completion);

                    Assert.Contains(" 500 ", exception.Message);
                }
                finally
                {
                    await longPollingTransport.StopAsync();
                }
            }
        }
Exemple #7
0
        public async Task LongPollingTransportSetsUserAgent()
        {
            HttpHeaderValueCollection <ProductInfoHeaderValue> userAgentHeaderCollection = null;

            var mockHttpHandler = new Mock <HttpMessageHandler>();

            mockHttpHandler.Protected()
            .Setup <Task <HttpResponseMessage> >("SendAsync", ItExpr.IsAny <HttpRequestMessage>(), ItExpr.IsAny <CancellationToken>())
            .Returns <HttpRequestMessage, CancellationToken>(async(request, cancellationToken) =>
            {
                userAgentHeaderCollection = request.Headers.UserAgent;
                await Task.Yield();
                return(ResponseUtils.CreateResponse(HttpStatusCode.OK));
            });

            using (var httpClient = new HttpClient(mockHttpHandler.Object))
            {
                var longPollingTransport = new LongPollingTransport(httpClient);

                try
                {
                    var pair = DuplexPipe.CreateConnectionPair(PipeOptions.Default, PipeOptions.Default);

                    Assert.Null(longPollingTransport.Mode);
                    await longPollingTransport.StartAsync(new Uri("http://fakeuri.org"), pair.Application, TransferMode.Text, connection : new TestConnection());
                }
                finally
                {
                    await longPollingTransport.StopAsync();
                }
            }

            Assert.NotNull(userAgentHeaderCollection);
            var userAgentHeader = Assert.Single(userAgentHeaderCollection);

            Assert.Equal("Microsoft.AspNetCore.Sockets.Client.Http", userAgentHeader.Product.Name);

            // user agent version should come from version embedded in assembly metadata
            var assemblyVersion = typeof(Constants)
                                  .Assembly
                                  .GetCustomAttribute <AssemblyInformationalVersionAttribute>();

            Assert.Equal(assemblyVersion.InformationalVersion, userAgentHeader.Product.Version);
        }
Exemple #8
0
        public async Task LongPollingTransportRePollsIfRequestCancelled()
        {
            var numPolls      = 0;
            var completionTcs = new TaskCompletionSource <object>();

            var mockHttpHandler = new Mock <HttpMessageHandler>();

            mockHttpHandler.Protected()
            .Setup <Task <HttpResponseMessage> >("SendAsync", ItExpr.IsAny <HttpRequestMessage>(), ItExpr.IsAny <CancellationToken>())
            .Returns <HttpRequestMessage, CancellationToken>(async(request, cancellationToken) =>
            {
                await Task.Yield();

                if (Interlocked.Increment(ref numPolls) < 3)
                {
                    throw new OperationCanceledException();
                }

                completionTcs.SetResult(null);
                return(ResponseUtils.CreateResponse(HttpStatusCode.OK));
            });

            using (var httpClient = new HttpClient(mockHttpHandler.Object))
            {
                var longPollingTransport = new LongPollingTransport(httpClient);

                try
                {
                    var connectionToTransport = Channel.CreateUnbounded <SendMessage>();
                    var transportToConnection = Channel.CreateUnbounded <byte[]>();
                    var channelConnection     = new ChannelConnection <SendMessage, byte[]>(connectionToTransport, transportToConnection);
                    await longPollingTransport.StartAsync(new Uri("http://fakeuri.org"), channelConnection, TransferMode.Binary, connectionId : string.Empty, connection : new TestConnection());

                    var completedTask = await Task.WhenAny(completionTcs.Task, longPollingTransport.Running).OrTimeout();

                    Assert.Equal(completionTcs.Task, completedTask);
                }
                finally
                {
                    await longPollingTransport.StopAsync();
                }
            }
        }
    public async Task LongPollingTransportShutsDownWhenChannelIsClosed()
    {
        var mockHttpHandler = new Mock <HttpMessageHandler>();
        var stopped         = false;

        mockHttpHandler.Protected()
        .Setup <Task <HttpResponseMessage> >("SendAsync", ItExpr.IsAny <HttpRequestMessage>(), ItExpr.IsAny <CancellationToken>())
        .Returns <HttpRequestMessage, CancellationToken>(async(request, cancellationToken) =>
        {
            await Task.Yield();
            if (request.Method == HttpMethod.Delete)
            {
                stopped = true;
                return(ResponseUtils.CreateResponse(HttpStatusCode.Accepted));
            }
            else
            {
                return(stopped
                        ? ResponseUtils.CreateResponse(HttpStatusCode.NoContent)
                        : ResponseUtils.CreateResponse(HttpStatusCode.OK));
            }
        });

        using (var httpClient = new HttpClient(mockHttpHandler.Object))
        {
            var longPollingTransport = new LongPollingTransport(httpClient);
            try
            {
                await longPollingTransport.StartAsync(TestUri, TransferFormat.Binary);

                longPollingTransport.Output.Complete();

                await longPollingTransport.Running.DefaultTimeout();

                await longPollingTransport.Input.ReadAllAsync().DefaultTimeout();
            }
            finally
            {
                await longPollingTransport.StopAsync();
            }
        }
    }
    [InlineData((TransferFormat)42)]                          // Unexpected value
    public async Task LongPollingTransportThrowsForInvalidTransferFormat(TransferFormat transferFormat)
    {
        var mockHttpHandler = new Mock <HttpMessageHandler>();

        mockHttpHandler.Protected()
        .Setup <Task <HttpResponseMessage> >("SendAsync", ItExpr.IsAny <HttpRequestMessage>(), ItExpr.IsAny <CancellationToken>())
        .Returns <HttpRequestMessage, CancellationToken>(async(request, cancellationToken) =>
        {
            await Task.Yield();
            return(ResponseUtils.CreateResponse(HttpStatusCode.OK));
        });

        using (var httpClient = new HttpClient(mockHttpHandler.Object))
        {
            var longPollingTransport = new LongPollingTransport(httpClient);
            var exception            = await Assert.ThrowsAsync <ArgumentException>(() =>
                                                                                    longPollingTransport.StartAsync(TestUri, transferFormat));

            Assert.Contains($"The '{transferFormat}' transfer format is not supported by this transport.", exception.Message);
            Assert.Equal("transferFormat", exception.ParamName);
        }
    }
Exemple #11
0
        public async Task LongPollingTransportStopsWhenPollRequestFails()
        {
            var mockHttpHandler = new Mock <HttpMessageHandler>();

            mockHttpHandler.Protected()
            .Setup <Task <HttpResponseMessage> >("SendAsync", ItExpr.IsAny <HttpRequestMessage>(), ItExpr.IsAny <CancellationToken>())
            .Returns <HttpRequestMessage, CancellationToken>(async(request, cancellationToken) =>
            {
                await Task.Yield();
                return(ResponseUtils.CreateResponse(HttpStatusCode.InternalServerError));
            });

            using (var httpClient = new HttpClient(mockHttpHandler.Object))
            {
                var longPollingTransport = new LongPollingTransport(httpClient);
                try
                {
                    var pair = DuplexPipe.CreateConnectionPair(PipeOptions.Default, PipeOptions.Default);
                    await longPollingTransport.StartAsync(new Uri("http://fakeuri.org"), pair.Application, TransferFormat.Binary, connection : new TestConnection());

                    var exception =
                        await Assert.ThrowsAsync <HttpRequestException>(async() =>
                    {
                        async Task ReadAsync()
                        {
                            await pair.Transport.Input.ReadAsync();
                        }

                        await ReadAsync().OrTimeout();
                    });

                    Assert.Contains(" 500 ", exception.Message);
                }
                finally
                {
                    await longPollingTransport.StopAsync();
                }
            }
        }
Exemple #12
0
        public async Task LongPollingTransportStopsPollAndSendLoopsWhenTransportStopped()
        {
            var mockHttpHandler = new Mock <HttpMessageHandler>();

            mockHttpHandler.Protected()
            .Setup <Task <HttpResponseMessage> >("SendAsync", ItExpr.IsAny <HttpRequestMessage>(), ItExpr.IsAny <CancellationToken>())
            .Returns <HttpRequestMessage, CancellationToken>(async(request, cancellationToken) =>
            {
                await Task.Yield();
                return(ResponseUtils.CreateResponse(HttpStatusCode.OK));
            });

            Task transportActiveTask;

            using (var httpClient = new HttpClient(mockHttpHandler.Object))
            {
                var longPollingTransport = new LongPollingTransport(httpClient);

                try
                {
                    var connectionToTransport = Channel.CreateUnbounded <SendMessage>();
                    var transportToConnection = Channel.CreateUnbounded <byte[]>();
                    var channelConnection     = new ChannelConnection <SendMessage, byte[]>(connectionToTransport, transportToConnection);
                    await longPollingTransport.StartAsync(new Uri("http://fakeuri.org"), channelConnection, TransferMode.Binary, connectionId : string.Empty, connection : new TestConnection());

                    transportActiveTask = longPollingTransport.Running;

                    Assert.False(transportActiveTask.IsCompleted);
                }
                finally
                {
                    await longPollingTransport.StopAsync();
                }

                await transportActiveTask.OrTimeout();
            }
        }
Exemple #13
0
        public async Task LongPollingTransportStopsWhenSendRequestFails()
        {
            var mockHttpHandler = new Mock <HttpMessageHandler>();

            mockHttpHandler.Protected()
            .Setup <Task <HttpResponseMessage> >("SendAsync", ItExpr.IsAny <HttpRequestMessage>(), ItExpr.IsAny <CancellationToken>())
            .Returns <HttpRequestMessage, CancellationToken>(async(request, cancellationToken) =>
            {
                await Task.Yield();
                var statusCode = request.Method == HttpMethod.Post
                        ? HttpStatusCode.InternalServerError
                        : HttpStatusCode.OK;
                return(ResponseUtils.CreateResponse(statusCode));
            });

            using (var httpClient = new HttpClient(mockHttpHandler.Object))
            {
                var longPollingTransport = new LongPollingTransport(httpClient);
                try
                {
                    await longPollingTransport.StartAsync(new Uri("http://fakeuri.org"), TransferFormat.Binary);

                    await longPollingTransport.Output.WriteAsync(Encoding.UTF8.GetBytes("Hello World"));

                    await longPollingTransport.Running.OrTimeout();

                    var exception = await Assert.ThrowsAsync <HttpRequestException>(async() => await longPollingTransport.Input.ReadAllAsync().OrTimeout());

                    Assert.Contains(" 500 ", exception.Message);
                }
                finally
                {
                    await longPollingTransport.StopAsync();
                }
            }
        }
    public async Task LongPollingTransportSendsAvailableMessagesWhenTheyArrive()
    {
        var sentRequests = new List <byte[]>();
        var tcs          = new TaskCompletionSource <HttpResponseMessage>();
        var firstPoll    = true;

        var mockHttpHandler = new Mock <HttpMessageHandler>();

        mockHttpHandler.Protected()
        .Setup <Task <HttpResponseMessage> >("SendAsync", ItExpr.IsAny <HttpRequestMessage>(), ItExpr.IsAny <CancellationToken>())
        .Returns <HttpRequestMessage, CancellationToken>(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)
            {
                // First poll completes immediately
                if (firstPoll)
                {
                    firstPoll = false;
                    return(ResponseUtils.CreateResponse(HttpStatusCode.OK));
                }

                cancellationToken.Register(() => tcs.TrySetCanceled(cancellationToken));
                // This is the poll task
                return(await tcs.Task);
            }
            else if (request.Method == HttpMethod.Delete)
            {
                return(ResponseUtils.CreateResponse(HttpStatusCode.Accepted));
            }
            return(ResponseUtils.CreateResponse(HttpStatusCode.OK));
        });

        using (var httpClient = new HttpClient(mockHttpHandler.Object))
        {
            var longPollingTransport = new LongPollingTransport(httpClient);

            try
            {
                // Start the transport
                await longPollingTransport.StartAsync(TestUri, TransferFormat.Binary);

                longPollingTransport.Output.Write(Encoding.UTF8.GetBytes("Hello"));
                longPollingTransport.Output.Write(Encoding.UTF8.GetBytes("World"));
                await longPollingTransport.Output.FlushAsync();

                longPollingTransport.Output.Complete();

                await longPollingTransport.Running.DefaultTimeout();

                await longPollingTransport.Input.ReadAllAsync();

                Assert.Single(sentRequests);
                Assert.Equal(new[] { (byte)'H', (byte)'e', (byte)'l', (byte)'l', (byte)'o', (byte)'W', (byte)'o', (byte)'r', (byte)'l', (byte)'d' }, sentRequests[0]);
            }
            finally
            {
                await longPollingTransport.StopAsync();
            }
        }
    }
Exemple #15
0
        public async Task LongPollingTransportThrowsForInvalidTransferMode()
        {
            var mockHttpHandler = new Mock <HttpMessageHandler>();

            mockHttpHandler.Protected()
            .Setup <Task <HttpResponseMessage> >("SendAsync", ItExpr.IsAny <HttpRequestMessage>(), ItExpr.IsAny <CancellationToken>())
            .Returns <HttpRequestMessage, CancellationToken>(async(request, cancellationToken) =>
            {
                await Task.Yield();
                return(ResponseUtils.CreateResponse(HttpStatusCode.OK));
            });

            using (var httpClient = new HttpClient(mockHttpHandler.Object))
            {
                var longPollingTransport = new LongPollingTransport(httpClient);
                var exception            = await Assert.ThrowsAsync <ArgumentException>(() =>
                                                                                        longPollingTransport.StartAsync(new Uri("http://fakeuri.org"), null, TransferMode.Text | TransferMode.Binary, connectionId: string.Empty, connection: new TestConnection()));

                Assert.Contains("Invalid transfer mode.", exception.Message);
                Assert.Equal("requestedTransferMode", exception.ParamName);
            }
        }
Exemple #16
0
        public async Task LongPollingTransportDispatchesMessagesReceivedFromPoll()
        {
            var message1Payload = new byte[] { (byte)'H', (byte)'e', (byte)'l', (byte)'l', (byte)'o' };

            var firstCall       = true;
            var mockHttpHandler = new Mock <HttpMessageHandler>();
            var sentRequests    = new List <HttpRequestMessage>();

            mockHttpHandler.Protected()
            .Setup <Task <HttpResponseMessage> >("SendAsync", ItExpr.IsAny <HttpRequestMessage>(), ItExpr.IsAny <CancellationToken>())
            .Returns <HttpRequestMessage, CancellationToken>(async(request, cancellationToken) =>
            {
                sentRequests.Add(request);

                await Task.Yield();

                if (firstCall)
                {
                    firstCall = false;
                    return(ResponseUtils.CreateResponse(HttpStatusCode.OK, message1Payload));
                }

                return(ResponseUtils.CreateResponse(HttpStatusCode.NoContent));
            });

            using (var httpClient = new HttpClient(mockHttpHandler.Object))
            {
                var longPollingTransport = new LongPollingTransport(httpClient);
                try
                {
                    var connectionToTransport = Channel.CreateUnbounded <SendMessage>();
                    var transportToConnection = Channel.CreateUnbounded <byte[]>();
                    var channelConnection     = new ChannelConnection <SendMessage, byte[]>(connectionToTransport, transportToConnection);

                    // Start the transport
                    await longPollingTransport.StartAsync(new Uri("http://fakeuri.org"), channelConnection, TransferMode.Binary, connectionId : string.Empty, connection : new TestConnection());

                    // Wait for the transport to finish
                    await longPollingTransport.Running.OrTimeout();

                    // Pull Messages out of the channel
                    var messages = new List <byte[]>();
                    while (await transportToConnection.Reader.WaitToReadAsync())
                    {
                        while (transportToConnection.Reader.TryRead(out var message))
                        {
                            messages.Add(message);
                        }
                    }

                    // Check the provided request
                    Assert.Equal(2, sentRequests.Count);

                    // Check the messages received
                    Assert.Single(messages);
                    Assert.Equal(message1Payload, messages[0]);
                }
                finally
                {
                    await longPollingTransport.StopAsync();
                }
            }
        }