public async Task LongPollingTransportShutsDownWhenChannelIsClosed() { 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); try { await longPollingTransport.StartAsync(new Uri("http://fakeuri.org"), TransferFormat.Binary); longPollingTransport.Output.Complete(); await longPollingTransport.Running.OrTimeout(); await longPollingTransport.Input.ReadAllAsync().OrTimeout(); } finally { await longPollingTransport.StopAsync(); } } }
public async Task LongPollingTransportSetsTransferFormat(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); try { var pair = DuplexPipe.CreateConnectionPair(PipeOptions.Default, PipeOptions.Default); await longPollingTransport.StartAsync(new Uri("http://fakeuri.org"), pair.Application, transferFormat, connection : new TestConnection()); } finally { await longPollingTransport.StopAsync(); } } }
public void SendSetsContentTypeAndWritesSerializedResponse() { var obj = new { A = 1 }; var context = new Mock <HttpContextBase>(); var request = new Mock <HttpRequestBase>(); var response = new Mock <HttpResponseBase>(); request.Setup(m => m.Path).Returns("/foo/"); var qs = new NameValueCollection(); qs["connectionId"] = "1"; request.Setup(m => m.QueryString).Returns(qs); context.Setup(m => m.Response).Returns(response.Object); context.Setup(m => m.Request).Returns(request.Object); var json = new Mock <IJsonSerializer>(); json.Setup(m => m.Stringify(obj)).Returns("A=1"); var heartBeat = new Mock <ITransportHeartBeat>(); var transport = new LongPollingTransport(context.Object, json.Object, heartBeat.Object); var connection = new Mock <IConnection>(); transport.Send(obj); response.VerifySet(m => m.ContentType = "application/json"); response.Verify(m => m.Write("A=1"), Times.Once()); }
public async Task LongPollingTransportStopsWhenPollReceives204() { 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.NoContent)); }); using (var httpClient = new HttpClient(mockHttpHandler.Object)) { var longPollingTransport = new LongPollingTransport(httpClient); try { await longPollingTransport.StartAsync(TestUri, TransferFormat.Binary); await longPollingTransport.Running.DefaultTimeout(); Assert.True(longPollingTransport.Input.TryRead(out var result)); Assert.True(result.IsCompleted); longPollingTransport.Input.AdvanceTo(result.Buffer.End); } finally { await longPollingTransport.StopAsync(); } } }
public async Task LongPollingTransportSetsTransferMode(TransferMode transferMode) { 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); try { var connectionToTransport = Channel.CreateUnbounded <SendMessage>(); var transportToConnection = Channel.CreateUnbounded <byte[]>(); var channelConnection = new ChannelConnection <SendMessage, byte[]>(connectionToTransport, transportToConnection); Assert.Null(longPollingTransport.Mode); await longPollingTransport.StartAsync(new Uri("http://fakeuri.org"), channelConnection, transferMode, connectionId : string.Empty, connection : new TestConnection()); Assert.Equal(transferMode, longPollingTransport.Mode); } finally { await longPollingTransport.StopAsync(); } } }
public async Task LongPollingTransportStopsWhenPollReceives204() { 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.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 = ChannelConnection.Create(connectionToTransport, transportToConnection); await longPollingTransport.StartAsync(new Uri("http://fakeuri.org"), channelConnection, TransferMode.Binary, connectionId : string.Empty, connection : new TestConnection()); await longPollingTransport.Running.OrTimeout(); Assert.True(transportToConnection.Reader.Completion.IsCompleted); } finally { await longPollingTransport.StopAsync(); } } }
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 { await longPollingTransport.StartAsync(TestUri, TransferFormat.Binary); transportActiveTask = longPollingTransport.Running; Assert.False(transportActiveTask.IsCompleted); } finally { await longPollingTransport.StopAsync(); } await transportActiveTask.DefaultTimeout(); } }
public void ConnectRequestRaisesConnectEvent() { var context = new Mock <HttpContextBase>(); var request = new Mock <HttpRequestBase>(); request.Setup(m => m.Path).Returns("/foo/connect"); var qs = new NameValueCollection(); qs["connectionId"] = "1"; request.Setup(m => m.QueryString).Returns(qs); context.Setup(m => m.Request).Returns(request.Object); var json = new Mock <IJsonSerializer>(); var heartBeat = new Mock <ITransportHeartBeat>(); var transport = new LongPollingTransport(context.Object, json.Object, heartBeat.Object); var connection = new Mock <IConnection>(); bool eventRaised = false; transport.Connected += () => { eventRaised = true; }; transport.ProcessRequest(connection.Object); Assert.True(eventRaised); }
public async Task LongPollingTransportSetsTransferFormat(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); try { await longPollingTransport.StartAsync(TestUri, transferFormat); } finally { await longPollingTransport.StopAsync(); } } }
public async Task TransportIsStoppedWhenConnectionIsStopped() { 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(request.Method == HttpMethod.Options ? ResponseUtils.CreateResponse(HttpStatusCode.OK, ResponseUtils.CreateNegotiationResponse()) : ResponseUtils.CreateResponse(HttpStatusCode.OK)); }); using (var httpClient = new HttpClient(mockHttpHandler.Object)) { var longPollingTransport = new LongPollingTransport(httpClient, new LoggerFactory()); var connection = new HttpConnection(new Uri("http://fakeuri.org/"), new TestTransportFactory(longPollingTransport), loggerFactory: null, httpMessageHandler: mockHttpHandler.Object); try { await connection.StartAsync(); Assert.False(longPollingTransport.Running.IsCompleted); } finally { await connection.DisposeAsync(); } await longPollingTransport.Running.OrTimeout(); } }
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 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); var exception = await Assert.ThrowsAsync <HttpRequestException>(async() => await transportToConnection.Reader.Completion.OrTimeout()); Assert.Contains(" 500 ", exception.Message); } finally { await longPollingTransport.StopAsync(); } } }
public async Task LongPollingTransportShutsDownImmediatelyEvenIfServerDoesntCompletePoll() { 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); try { await longPollingTransport.StartAsync(TestUri, TransferFormat.Binary); longPollingTransport.Output.Complete(); await longPollingTransport.Running.DefaultTimeout(); await longPollingTransport.Input.ReadAllAsync().DefaultTimeout(); } finally { await longPollingTransport.StopAsync(); } } }
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 pair = DuplexPipe.CreateConnectionPair(PipeOptions.Default, PipeOptions.Default); await longPollingTransport.StartAsync(new Uri("http://fakeuri.org"), pair.Application, TransferMode.Binary, connection : new TestConnection()); transportActiveTask = longPollingTransport.Running; Assert.False(transportActiveTask.IsCompleted); } finally { await longPollingTransport.StopAsync(); } await transportActiveTask.OrTimeout(); } }
public async Task LongPollingTransportStopsWhenPollReceives204() { 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.NoContent)); }); 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, TransferMode.Binary, connection : new TestConnection()); await longPollingTransport.Running.OrTimeout(); Assert.True(pair.Transport.Input.TryRead(out var result)); Assert.True(result.IsCompleted); pair.Transport.Input.AdvanceTo(result.Buffer.End); } finally { await longPollingTransport.StopAsync(); } } }
public async Task MultipleFramesSentAsSingleResponse() { var channel = Channel.CreateUnbounded <byte[]>(); var context = new DefaultHttpContext(); var poll = new LongPollingTransport(CancellationToken.None, channel, connectionId: string.Empty, loggerFactory: new LoggerFactory()); var ms = new MemoryStream(); context.Response.Body = ms; await channel.Out.WriteAsync(Encoding.UTF8.GetBytes("Hello")); await channel.Out.WriteAsync(Encoding.UTF8.GetBytes(" ")); await channel.Out.WriteAsync(Encoding.UTF8.GetBytes("World")); Assert.True(channel.Out.TryComplete()); await poll.ProcessRequestAsync(context, context.RequestAborted); Assert.Equal(200, context.Response.StatusCode); var payload = ms.ToArray(); Assert.Equal("Hello World", Encoding.UTF8.GetString(payload)); }
public async Task PollingLoopNotRestartedIfStartFails() { var disconnectCts = new CancellationTokenSource(); var mockConnection = new Mock <Client.IConnection>(); mockConnection.SetupGet(c => c.JsonSerializer).Returns(JsonSerializer.CreateDefault()); mockConnection.Setup(c => c.TotalTransportConnectTimeout).Returns(TimeSpan.FromSeconds(500)); mockConnection.SetupProperty(c => c.MessageId); var mockHttpClient = CreateFakeHttpClient((url, request, postData, isLongRunning) => Task.FromException <IResponse>(new InvalidOperationException("Request rejected"))); mockHttpClient.Setup( m => m.Get(It.IsAny <string>(), It.IsAny <Action <Client.Http.IRequest> >(), It.IsAny <bool>())) .Returns <string, Action <Client.Http.IRequest>, bool>( (url, request, isLongRunning) => Task.FromResult(CreateResponse("{ \"Response\" : \"started\"}"))); var longPollingTransport = new LongPollingTransport(mockHttpClient.Object); await Assert.ThrowsAsync <InvalidOperationException>(() => longPollingTransport.Start(mockConnection.Object, string.Empty, disconnectCts.Token)) .OrTimeout(TimeSpan.FromSeconds(15)); // give it some time to settle await Task.Delay(1000); mockHttpClient .Verify(c => c.Post(It.Is <string>(url => url.StartsWith("poll?")), It.IsAny <Action <Client.Http.IRequest> >(), It.IsAny <IDictionary <string, string> >(), It.IsAny <bool>()), Times.Never()); }
public void SendRequestRaisesOnReceived() { var context = new Mock <HttpContextBase>(); var request = new Mock <HttpRequestBase>(); request.Setup(m => m.Path).Returns("/foo/send"); var form = new NameValueCollection(); form["data"] = "some data"; request.Setup(m => m.Form).Returns(form); context.Setup(m => m.Request).Returns(request.Object); var json = new Mock <IJsonStringifier>(); var heartBeat = new Mock <ITransportHeartBeat>(); var transport = new LongPollingTransport(context.Object, json.Object, heartBeat.Object); var connection = new Mock <IConnection>(); bool eventRaised = false; transport.Received += data => { eventRaised = true; Assert.Equal(data, "some data"); }; transport.ProcessRequest(connection.Object); Assert.True(eventRaised); }
public async Task LongPollingTransportStartAsyncFailsIfFirstRequestFails() { 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 exception = await Assert.ThrowsAsync <HttpRequestException>(() => longPollingTransport.StartAsync(TestUri, TransferFormat.Binary)); Assert.Contains(" 500 ", exception.Message); } finally { await longPollingTransport.StopAsync(); } } }
public async Task MultipleFramesSentAsSingleResponse() { var pair = DuplexPipe.CreateConnectionPair(PipeOptions.Default, PipeOptions.Default); var connection = new DefaultConnectionContext("foo", pair.Transport, pair.Application); var context = new DefaultHttpContext(); var poll = new LongPollingTransport(CancellationToken.None, connection.Application.Input, loggerFactory: new LoggerFactory()); var ms = new MemoryStream(); context.Response.Body = ms; await connection.Transport.Output.WriteAsync(Encoding.UTF8.GetBytes("Hello")); await connection.Transport.Output.WriteAsync(Encoding.UTF8.GetBytes(" ")); await connection.Transport.Output.WriteAsync(Encoding.UTF8.GetBytes("World")); connection.Transport.Output.Complete(); await poll.ProcessRequestAsync(context, context.RequestAborted).OrTimeout(); Assert.Equal(200, context.Response.StatusCode); var payload = ms.ToArray(); Assert.Equal("Hello World", Encoding.UTF8.GetString(payload)); }
public async Task LongPollingTransportSendsDeleteAfterPollEnds() { var sentRequests = new List <byte[]>(); var pollTcs = new TaskCompletionSource <HttpResponseMessage>(); var deleteTcs = new TaskCompletionSource(); 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(() => 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(); 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.DefaultTimeout(); await task.DefaultTimeout(); } }
public async Task LongPollingTransportSendsAvailableMessagesWhenTheyArrive() { var sentRequests = new List <byte[]>(); var tcs = new TaskCompletionSource <HttpResponseMessage>(); 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) { 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.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 LongPollingTransportResponseWithNoContentDoesNotStopPoll() { int requests = 0; 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 (requests == 0) { requests++; return(ResponseUtils.CreateResponse(HttpStatusCode.OK, "Hello")); } else if (requests == 1) { requests++; // Time out return(ResponseUtils.CreateResponse(HttpStatusCode.OK)); } else if (requests == 2) { requests++; return(ResponseUtils.CreateResponse(HttpStatusCode.OK, "World")); } // Done 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); await longPollingTransport.StartAsync(new Uri("http://fakeuri.org"), channelConnection, TransferMode.Binary, connectionId : string.Empty, connection : new TestConnection()); var data = await transportToConnection.Reader.ReadAllAsync().OrTimeout(); await longPollingTransport.Running.OrTimeout(); Assert.True(transportToConnection.Reader.Completion.IsCompleted); Assert.Equal(2, data.Count); Assert.Equal(Encoding.UTF8.GetBytes("Hello"), data[0]); Assert.Equal(Encoding.UTF8.GetBytes("World"), data[1]); } finally { await longPollingTransport.StopAsync(); } } }
public async Task LongPollingTransportDispatchesMessagesReceivedFromPoll() { var message1Payload = new[] { (byte)'H', (byte)'e', (byte)'l', (byte)'l', (byte)'o' }; var requests = 0; 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 (requests == 0) { requests++; return(ResponseUtils.CreateResponse(HttpStatusCode.OK)); } else if (requests == 1) { requests++; return(ResponseUtils.CreateResponse(HttpStatusCode.OK, message1Payload)); } return(ResponseUtils.CreateResponse(HttpStatusCode.NoContent)); }); using (var httpClient = new HttpClient(mockHttpHandler.Object)) { var longPollingTransport = new LongPollingTransport(httpClient); try { // Start the transport await longPollingTransport.StartAsync(TestUri, TransferFormat.Binary); // Wait for the transport to finish await longPollingTransport.Running.DefaultTimeout(); // Pull Messages out of the channel var message = await longPollingTransport.Input.ReadAllAsync(); // Check the provided request Assert.Equal(3, sentRequests.Count); // Check the messages received Assert.Equal(message1Payload, message); } finally { await longPollingTransport.StopAsync(); } } }
public async Task LongPollingTransportResponseWithNoContentDoesNotStopPoll() { var requests = 0; 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 (requests == 0) { requests++; return(ResponseUtils.CreateResponse(HttpStatusCode.OK)); } else if (requests == 1) { requests++; return(ResponseUtils.CreateResponse(HttpStatusCode.OK, "Hello")); } else if (requests == 2) { requests++; // Time out return(ResponseUtils.CreateResponse(HttpStatusCode.OK)); } else if (requests == 3) { requests++; return(ResponseUtils.CreateResponse(HttpStatusCode.OK, "World")); } // Done return(ResponseUtils.CreateResponse(HttpStatusCode.NoContent)); }); using (var httpClient = new HttpClient(mockHttpHandler.Object)) { var longPollingTransport = new LongPollingTransport(httpClient); try { await longPollingTransport.StartAsync(TestUri, TransferFormat.Binary); var data = await longPollingTransport.Input.ReadAllAsync().DefaultTimeout(); await longPollingTransport.Running.DefaultTimeout(); Assert.Equal(Encoding.UTF8.GetBytes("HelloWorld"), data); } finally { await longPollingTransport.StopAsync(); } } }
static void Main(string[] args) { Thread.Sleep(3000); var baseUrl = "http://localhost:5000/hubs/testHub"; var loggerFactory = new LoggerFactory(); loggerFactory.AddConsole() .AddDebug(); var logger = loggerFactory.CreateLogger <Program>(); var cts = new CancellationTokenSource(); Console.CancelKeyPress += (sender, a) => { a.Cancel = true; logger.LogInformation("Stopping loops..."); cts.Cancel(); }; using (var httpClient = new HttpClient(new LoggingMessageHandler(loggerFactory, new HttpClientHandler()))) { var transport = new LongPollingTransport(httpClient, loggerFactory); var connection = new HubConnection(new Uri(baseUrl), new JsonNetInvocationAdapter(), loggerFactory); try { logger.LogInformation("Connecting to {0}", baseUrl); connection.StartAsync(transport, httpClient).GetAwaiter(); logger.LogInformation("Connected to {0}", baseUrl); connection.On("echo", new[] { typeof(string) }, a => { var message = (string)a[0]; logger.LogInformation("RECEIVED: " + message); }); var result = connection.Invoke <string>("echo").GetAwaiter(); while (!cts.Token.IsCancellationRequested) { //var line = Console.ReadLine(); //logger.LogInformation("Sending: {0}", line); // //connection.Invoke<object>("Send", line).GetAwaiter(); } } finally { connection.DisposeAsync().GetAwaiter(); } } }
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 { var connectionToTransport = Channel.CreateUnbounded <SendMessage>(); var transportToConnection = Channel.CreateUnbounded <byte[]>(); var channelConnection = new ChannelConnection <SendMessage, byte[]>(connectionToTransport, transportToConnection); var tcs1 = new TaskCompletionSource <object>(); var tcs2 = new TaskCompletionSource <object>(); // Pre-queue some messages await connectionToTransport.Writer.WriteAsync(new SendMessage(Encoding.UTF8.GetBytes("Hello"), tcs1)).OrTimeout(); await connectionToTransport.Writer.WriteAsync(new SendMessage(Encoding.UTF8.GetBytes("World"), tcs2)).OrTimeout(); // Start the transport await longPollingTransport.StartAsync(new Uri("http://fakeuri.org"), channelConnection, TransferMode.Binary, connectionId : string.Empty, connection : new TestConnection()); connectionToTransport.Writer.Complete(); await longPollingTransport.Running.OrTimeout(); await connectionToTransport.Reader.Completion.OrTimeout(); Assert.Single(sentRequests); Assert.Equal(new byte[] { (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 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 pair = DuplexPipe.CreateConnectionPair(PipeOptions.Default, PipeOptions.Default); // Start the transport await longPollingTransport.StartAsync(new Uri("http://fakeuri.org"), pair.Application, TransferFormat.Binary, connection : new TestConnection()); // Wait for the transport to finish await longPollingTransport.Running.OrTimeout(); // Pull Messages out of the channel var message = await pair.Transport.Input.ReadAllAsync(); // Check the provided request Assert.Equal(2, sentRequests.Count); // Check the messages received Assert.Equal(message1Payload, message); } finally { await longPollingTransport.StopAsync(); } } }
public async Task Set204StatusCodeWhenChannelComplete() { var channel = Channel.CreateUnbounded <byte[]>(); var context = new DefaultHttpContext(); var poll = new LongPollingTransport(CancellationToken.None, channel, connectionId: string.Empty, loggerFactory: new LoggerFactory()); Assert.True(channel.Out.TryComplete()); await poll.ProcessRequestAsync(context, context.RequestAborted); Assert.Equal(204, context.Response.StatusCode); }
public async Task LongPollingTransportStopsWhenSendRequestFails() { var stopped = false; 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(); switch (request.Method.Method) { case "DELETE": stopped = true; return(ResponseUtils.CreateResponse(HttpStatusCode.Accepted)); case "GET" when stopped: return(ResponseUtils.CreateResponse(HttpStatusCode.NoContent)); case "GET": return(ResponseUtils.CreateResponse(HttpStatusCode.OK)); case "POST": return(ResponseUtils.CreateResponse(HttpStatusCode.InternalServerError)); default: throw new InvalidOperationException("Unexpected request"); } }); using (var httpClient = new HttpClient(mockHttpHandler.Object)) { var longPollingTransport = new LongPollingTransport(httpClient); try { await longPollingTransport.StartAsync(TestUri, TransferFormat.Binary); await longPollingTransport.Output.WriteAsync(Encoding.UTF8.GetBytes("Hello World")); await longPollingTransport.Running.DefaultTimeout(); var exception = await Assert.ThrowsAsync <HttpRequestException>(async() => await longPollingTransport.Input.ReadAllAsync().DefaultTimeout()); Assert.Contains(" 500 ", exception.Message); Assert.True(stopped); } finally { await longPollingTransport.StopAsync(); } } }
public async Task LongPollingDoesNotPollAfterTransportIsBeingStoppedMidRequest() { var disconnectCts = new CancellationTokenSource(); var mockConnection = new Mock <Client.IConnection>(); mockConnection.SetupGet(c => c.JsonSerializer).Returns(JsonSerializer.CreateDefault()); mockConnection.Setup(c => c.TotalTransportConnectTimeout).Returns(TimeSpan.FromSeconds(10)); mockConnection.SetupProperty(c => c.MessageId); var pollingTcs = new TaskCompletionSource <object>(TaskCreationOptions.RunContinuationsAsynchronously); var mockHttpClient = CreateFakeHttpClient( (url, request, postData, isLongRunning) => { var responseMessage = string.Empty; if (url.Contains("connect?")) { responseMessage = "{\"C\":\"d-C6243495-A,0|B,0|C,1|D,0\",\"S\":1,\"M\":[]}"; } else if (url.Contains("poll?")) { pollingTcs.TrySetResult(null); // stop polling loop disconnectCts.Cancel(); } return(Task.FromResult(CreateResponse(responseMessage))); }); var longPollingTransport = new LongPollingTransport(mockHttpClient.Object); try { await longPollingTransport.Start(mockConnection.Object, string.Empty, disconnectCts.Token) .OrTimeout(TimeSpan.FromSeconds(15)); } catch (StartException stex) when(stex.InnerException is OperationCanceledException) { // An OCE is expected sometimes, depending on a race condition. } await pollingTcs.Task.OrTimeout(TimeSpan.FromSeconds(2)); // give it some time to make sure a new poll was not setup after verification await Task.Delay(1000); mockHttpClient .Verify(c => c.Post(It.Is <string>(url => url.StartsWith("poll?")), It.IsAny <Action <Client.Http.IRequest> >(), It.IsAny <IDictionary <string, string> >(), It.IsAny <bool>()), Times.Once()); }