public async Task CanStartAndStopConnectionUsingGivenTransport(HttpTransportType transportType) { using (StartVerifiableLog(out var loggerFactory, minLogLevel: LogLevel.Trace, testName: $"CanStartAndStopConnectionUsingGivenTransport_{transportType}")) { var url = ServerFixture.Url + "/echo"; var connection = new HttpConnection(new Uri(url), transportType, loggerFactory); await connection.StartAsync(TransferFormat.Text).OrTimeout(); await connection.DisposeAsync().OrTimeout(); } }
public async Task CanStartAndStopConnectionUsingGivenTransport(HttpTransportType transportType) { using (StartServer <Startup>(out var server)) { var url = server.Url + "/echo"; var connection = new HttpConnection(new Uri(url), transportType, LoggerFactory); await connection.StartAsync(TransferFormat.Text).OrTimeout(); await connection.DisposeAsync().OrTimeout(); } }
public static async Task <int> ExecuteAsync(string baseUrl) { baseUrl = string.IsNullOrEmpty(baseUrl) ? "http://localhost:5000/chat" : baseUrl; var loggerFactory = new LoggerFactory(); var logger = loggerFactory.CreateLogger <Program>(); Console.WriteLine($"Connecting to {baseUrl}..."); var connection = new HttpConnection(new Uri(baseUrl), loggerFactory); try { var cts = new CancellationTokenSource(); connection.OnReceived(data => Console.Out.WriteLineAsync($"{Encoding.UTF8.GetString(data)}")); connection.Closed += e => { cts.Cancel(); return(Task.CompletedTask); }; await connection.StartAsync(); Console.WriteLine($"Connected to {baseUrl}"); Console.CancelKeyPress += (sender, a) => { a.Cancel = true; cts.Cancel(); }; while (!cts.Token.IsCancellationRequested) { var line = await Task.Run(() => Console.ReadLine(), cts.Token); if (line == null) { break; } await connection.SendAsync(Encoding.UTF8.GetBytes(line), cts.Token); } } catch (AggregateException aex) when(aex.InnerExceptions.All(e => e is OperationCanceledException)) { } catch (OperationCanceledException) { } finally { await connection.DisposeAsync(); } return(0); }
public async Task ConnectionCanSendAndReceiveDifferentMessageSizesWebSocketsTransport(string message) { using (StartLog(out var loggerFactory, testName: $"ConnectionCanSendAndReceiveDifferentMessageSizesWebSocketsTransport_{message.Length}")) { var logger = loggerFactory.CreateLogger <EndToEndTests>(); var url = _serverFixture.BaseUrl + "/echo"; var connection = new HttpConnection(new Uri(url), TransportType.WebSockets, loggerFactory); connection.Features.Set <ITransferModeFeature>( new TransferModeFeature { TransferMode = TransferMode.Binary }); try { var receiveTcs = new TaskCompletionSource <byte[]>(); connection.Received += data => { logger.LogInformation("Received {length} byte message", data.Length); receiveTcs.TrySetResult(data); return(Task.CompletedTask); }; logger.LogInformation("Starting connection to {url}", url); await connection.StartAsync().OrTimeout(); logger.LogInformation("Started connection to {url}", url); var bytes = Encoding.UTF8.GetBytes(message); logger.LogInformation("Sending {length} byte message", bytes.Length); await connection.SendAsync(bytes).OrTimeout(); logger.LogInformation("Sent message", bytes.Length); logger.LogInformation("Receiving message"); var receivedData = await receiveTcs.Task.OrTimeout(); Assert.Equal(message, Encoding.UTF8.GetString(receivedData)); logger.LogInformation("Completed receive"); } catch (Exception ex) { logger.LogInformation(ex, "Test threw exception"); throw; } finally { logger.LogInformation("Disposing Connection"); await connection.DisposeAsync().OrTimeout(); logger.LogInformation("Disposed Connection"); } } }
public async Task ReceivedCallbackNotRaisedAfterConnectionIsDisposed() { 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(IsNegotiateRequest(request) ? ResponseUtils.CreateResponse(HttpStatusCode.OK, ResponseUtils.CreateNegotiationResponse()) : ResponseUtils.CreateResponse(HttpStatusCode.OK)); }); var mockTransport = new Mock <ITransport>(); Channel <byte[], SendMessage> channel = null; mockTransport.Setup(t => t.StartAsync(It.IsAny <Uri>(), It.IsAny <Channel <byte[], SendMessage> >(), It.IsAny <TransferMode>(), It.IsAny <string>())) .Returns <Uri, Channel <byte[], SendMessage>, TransferMode, string>((url, c, transferMode, connectionId) => { channel = c; return(Task.CompletedTask); }); mockTransport.Setup(t => t.StopAsync()) .Returns(() => { // The connection is now in the Disconnected state so the Received event for // this message should not be raised channel.Writer.TryWrite(Array.Empty <byte>()); channel.Writer.TryComplete(); return(Task.CompletedTask); }); mockTransport.SetupGet(t => t.Mode).Returns(TransferMode.Text); var connection = new HttpConnection(new Uri("http://fakeuri.org/"), new TestTransportFactory(mockTransport.Object), loggerFactory: null, httpOptions: new HttpOptions { HttpMessageHandler = mockHttpHandler.Object }); var onReceivedInvoked = false; connection.OnReceived(_ => { onReceivedInvoked = true; return(Task.CompletedTask); }); await connection.StartAsync(); await connection.DisposeAsync(); Assert.False(onReceivedInvoked); }
public async Task TransportThatFallsbackCreatesNewConnection() { var url = _serverFixture.Url + "/echo"; // The test should connect to the server using WebSockets transport on Windows 8 and newer. // On Windows 7/2008R2 it should use ServerSentEvents transport to connect to the server. // The test logic lives in the TestTransportFactory and FakeTransport. var connection = new HttpConnection(new Uri(url), new TestTransportFactory(), null, null); await connection.StartAsync(TransferFormat.Text).OrTimeout(); await connection.DisposeAsync().OrTimeout(); }
private static async Task WithConnectionAsync(HttpConnection connection, Func <HttpConnection, Task> body) { try { // Using OrTimeout here will hide any timeout issues in the test :(. await body(connection); } finally { await connection.DisposeAsync().OrTimeout(); } }
public async Task ConnectionCanSendAndReceiveMessages(HttpTransportType transportType, TransferFormat requestedTransferFormat) { using (StartServer <Startup>(out var server)) { var logger = LoggerFactory.CreateLogger <EndToEndTests>(); const string message = "Major Key"; var url = server.Url + "/echo"; var connection = new HttpConnection(new Uri(url), transportType, LoggerFactory); try { logger.LogInformation("Starting connection to {url}", url); await connection.StartAsync(requestedTransferFormat).OrTimeout(); logger.LogInformation("Started connection to {url}", url); var bytes = Encoding.UTF8.GetBytes(message); logger.LogInformation("Sending {length} byte message", bytes.Length); try { await connection.Transport.Output.WriteAsync(bytes).OrTimeout(); } catch (OperationCanceledException) { // Because the server and client are run in the same process there is a race where websocket.SendAsync // can send a message but before returning be suspended allowing the server to run the EchoConnectionHandler and // send a close frame which triggers a cancellation token on the client and cancels the websocket.SendAsync. // Our solution to this is to just catch OperationCanceledException from the sent message if the race happens // because we know the send went through, and its safe to check the response. } logger.LogInformation("Sent message"); logger.LogInformation("Receiving message"); Assert.Equal(message, Encoding.UTF8.GetString(await connection.Transport.Input.ReadAsync(bytes.Length).OrTimeout())); logger.LogInformation("Completed receive"); } catch (Exception ex) { logger.LogInformation(ex, "Test threw exception"); throw; } finally { logger.LogInformation("Disposing Connection"); await connection.DisposeAsync().OrTimeout(); logger.LogInformation("Disposed Connection"); } } }
public async Task EventQueueTimeoutWithException() { 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(IsNegotiateRequest(request) ? ResponseUtils.CreateResponse(HttpStatusCode.OK, ResponseUtils.CreateNegotiationResponse()) : ResponseUtils.CreateResponse(HttpStatusCode.OK)); }); var mockTransport = new Mock <ITransport>(); Channel <byte[], SendMessage> channel = null; mockTransport.Setup(t => t.StartAsync(It.IsAny <Uri>(), It.IsAny <Channel <byte[], SendMessage> >(), It.IsAny <TransferMode>(), It.IsAny <string>())) .Returns <Uri, Channel <byte[], SendMessage>, TransferMode, string>((url, c, transferMode, connectionId) => { channel = c; return(Task.CompletedTask); }); mockTransport.Setup(t => t.StopAsync()) .Returns(() => { channel.Writer.TryComplete(); return(Task.CompletedTask); }); mockTransport.SetupGet(t => t.Mode).Returns(TransferMode.Text); var callbackInvokedTcs = new TaskCompletionSource <object>(); var connection = new HttpConnection(new Uri("http://fakeuri.org/"), new TestTransportFactory(mockTransport.Object), loggerFactory: null, httpOptions: new HttpOptions { HttpMessageHandler = mockHttpHandler.Object }); connection.OnReceived(_ => { throw new OperationCanceledException(); }); await connection.StartAsync(); channel.Writer.TryWrite(Array.Empty <byte>()); // Ensure that SignalR isn't blocked by the receive callback Assert.False(channel.Reader.TryRead(out var message)); await connection.DisposeAsync(); }
public async Task ConnectionCanSendAndReceiveDifferentMessageSizesWebSocketsTransport(string message) { using (StartLog(out var loggerFactory, LogLevel.Trace, testName: $"ConnectionCanSendAndReceiveDifferentMessageSizesWebSocketsTransport_{message.Length}")) { var logger = loggerFactory.CreateLogger <EndToEndTests>(); var url = _serverFixture.Url + "/echo"; var connection = new HttpConnection(new Uri(url), TransportType.WebSockets, loggerFactory); try { var receiveTcs = new TaskCompletionSource <byte[]>(); connection.OnReceived((data, state) => { logger.LogInformation("Received {length} byte message", data.Length); var tcs = (TaskCompletionSource <byte[]>)state; tcs.TrySetResult(data); return(Task.CompletedTask); }, receiveTcs); logger.LogInformation("Starting connection to {url}", url); await connection.StartAsync(TransferFormat.Binary).OrTimeout(); logger.LogInformation("Started connection to {url}", url); var bytes = Encoding.UTF8.GetBytes(message); logger.LogInformation("Sending {length} byte message", bytes.Length); await connection.SendAsync(bytes).OrTimeout(); logger.LogInformation("Sent message", bytes.Length); logger.LogInformation("Receiving message"); // Big timeout here because it can take a while to receive all the bytes var receivedData = await receiveTcs.Task.OrTimeout(TimeSpan.FromSeconds(30)); Assert.Equal(message, Encoding.UTF8.GetString(receivedData)); logger.LogInformation("Completed receive"); } catch (Exception ex) { logger.LogInformation(ex, "Test threw exception"); throw; } finally { logger.LogInformation("Disposing Connection"); await connection.DisposeAsync().OrTimeout(); logger.LogInformation("Disposed Connection"); } } }
public async Task CanStartAndStopConnectionUsingGivenTransport(HttpTransportType transportType) { using (var server = await StartServer <Startup>()) { var url = server.Url + "/echo"; var connection = new HttpConnection(new HttpConnectionOptions { Url = new Uri(url), Transports = transportType, DefaultTransferFormat = TransferFormat.Text }, LoggerFactory); await connection.StartAsync().OrTimeout(); await connection.DisposeAsync().OrTimeout(); } }
public async Task CanStartAndStopConnectionUsingDefaultTransport() { using (StartServer <Startup>(out var server)) { var url = server.Url + "/echo"; // The test should connect to the server using WebSockets transport on Windows 8 and newer. // On Windows 7/2008R2 it should use ServerSentEvents transport to connect to the server. var connection = new HttpConnection(new Uri(url), HttpTransports.All, LoggerFactory); await connection.StartAsync(TransferFormat.Binary).OrTimeout(); await connection.DisposeAsync().OrTimeout(); } }
public async Task HTTPRequestsNotSentWhenWebSocketsTransportRequested() { using (StartLog(out var loggerFactory)) { var logger = loggerFactory.CreateLogger <EndToEndTests>(); var url = _serverFixture.Url + "/echo"; var mockHttpHandler = new Mock <HttpMessageHandler>(); mockHttpHandler.Protected() .Setup <Task <HttpResponseMessage> >("SendAsync", ItExpr.IsAny <HttpRequestMessage>(), ItExpr.IsAny <CancellationToken>()) .Returns <HttpRequestMessage, CancellationToken>( (request, cancellationToken) => Task.FromException <HttpResponseMessage>(new InvalidOperationException("HTTP requests should not be sent."))); var connection = new HttpConnection(new Uri(url), TransportType.WebSockets, loggerFactory, new HttpOptions { HttpMessageHandler = mockHttpHandler.Object }); try { var receiveTcs = new TaskCompletionSource <byte[]>(); connection.OnReceived((data, state) => { var tcs = (TaskCompletionSource <byte[]>)state; tcs.TrySetResult(data); return(Task.CompletedTask); }, receiveTcs); var message = new byte[] { 42 }; await connection.StartAsync().OrTimeout(); await connection.SendAsync(message).OrTimeout(); var receivedData = await receiveTcs.Task.OrTimeout(); Assert.Equal(message, receivedData); } catch (Exception ex) { logger.LogInformation(ex, "Test threw exception"); throw; } finally { logger.LogInformation("Disposing Connection"); await connection.DisposeAsync().OrTimeout(); logger.LogInformation("Disposed Connection"); } } }
public async Task CannotStartDisposedConnection() { using (var httpClient = new HttpClient()) { var connection = new HttpConnection(new Uri("http://fakeuri.org/")); await connection.DisposeAsync(); var exception = await Assert.ThrowsAsync <InvalidOperationException>( async() => await connection.StartAsync()); Assert.Equal("Cannot start a connection that is not in the Initial state.", exception.Message); } }
public async Task AuthorizedConnectionCanConnect() { bool ExpectedErrors(WriteContext writeContext) { return(writeContext.LoggerName == typeof(HttpConnection).FullName && writeContext.EventId.Name == "ErrorWithNegotiation"); } using (var server = await StartServer <Startup>(ExpectedErrors)) { var logger = LoggerFactory.CreateLogger <EndToEndTests>(); string token; using (var client = new HttpClient()) { client.BaseAddress = new Uri(server.Url); var response = await client.GetAsync("generatetoken?user=bob"); token = await response.Content.ReadAsStringAsync(); } var url = server.Url + "/auth"; var connection = new HttpConnection( new HttpConnectionOptions() { Url = new Uri(url), AccessTokenProvider = () => Task.FromResult(token), Transports = HttpTransportType.ServerSentEvents, DefaultTransferFormat = TransferFormat.Text, }, LoggerFactory); try { logger.LogInformation("Starting connection to {url}", url); await connection.StartAsync().OrTimeout(); logger.LogInformation("Connected to {url}", url); } finally { logger.LogInformation("Disposing Connection"); await connection.DisposeAsync().OrTimeout(); logger.LogInformation("Disposed Connection"); } } }
public async Task HttpRequestsNotSentWhenWebSocketsTransportRequestedAndSkipNegotiationSet() { using (StartServer <Startup>(out var server)) { var logger = LoggerFactory.CreateLogger <EndToEndTests>(); var url = server.Url + "/echo"; var mockHttpHandler = new Mock <HttpMessageHandler>(); mockHttpHandler.Protected() .Setup <Task <HttpResponseMessage> >("SendAsync", ItExpr.IsAny <HttpRequestMessage>(), ItExpr.IsAny <CancellationToken>()) .Returns <HttpRequestMessage, CancellationToken>( (request, cancellationToken) => Task.FromException <HttpResponseMessage>(new InvalidOperationException("HTTP requests should not be sent."))); var httpOptions = new HttpConnectionOptions { Url = new Uri(url), Transports = HttpTransportType.WebSockets, SkipNegotiation = true, HttpMessageHandlerFactory = (httpMessageHandler) => mockHttpHandler.Object }; var connection = new HttpConnection(httpOptions, LoggerFactory); try { var message = new byte[] { 42 }; await connection.StartAsync(TransferFormat.Binary).OrTimeout(); await connection.Transport.Output.WriteAsync(message).OrTimeout(); var receivedData = await connection.Transport.Input.ReadAsync(1); Assert.Equal(message, receivedData); } catch (Exception ex) { logger.LogInformation(ex, "Test threw exception"); throw; } finally { logger.LogInformation("Disposing Connection"); await connection.DisposeAsync().OrTimeout(); logger.LogInformation("Disposed Connection"); } } }
public async Task ClosedEventNotRaisedWhenTheClientIsStoppedButWasNeverStarted() { var connection = new HttpConnection(new Uri("http://fakeuri.org/")); bool closedEventRaised = false; connection.Closed += e => { closedEventRaised = true; return(Task.CompletedTask); }; await connection.DisposeAsync(); Assert.False(closedEventRaised); }
public async Task CanStopStartingConnection() { // Used to make sure StartAsync is not completed before DisposeAsync is called var releaseNegotiateTcs = new TaskCompletionSource <object>(); // Used to make sure that DisposeAsync runs after we check the state in StartAsync var allowDisposeTcs = new TaskCompletionSource <object>(); // Used to make sure that DisposeAsync continues only after StartAsync finished var releaseDisposeTcs = 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(); // allow DisposeAsync to continue once we know we are past the connection state check allowDisposeTcs.SetResult(null); await releaseNegotiateTcs.Task; return(IsNegotiateRequest(request) ? ResponseUtils.CreateResponse(HttpStatusCode.OK, ResponseUtils.CreateNegotiationResponse()) : ResponseUtils.CreateResponse(HttpStatusCode.OK)); }); var transport = new Mock <ITransport>(); transport.Setup(t => t.StopAsync()).Returns(async() => { await releaseDisposeTcs.Task; }); var connection = new HttpConnection(new Uri("http://fakeuri.org/"), new TestTransportFactory(transport.Object), loggerFactory: null, httpOptions: new HttpOptions { HttpMessageHandler = mockHttpHandler.Object }); var startTask = connection.StartAsync(); await allowDisposeTcs.Task; var disposeTask = connection.DisposeAsync(); // allow StartAsync to continue once DisposeAsync has started releaseNegotiateTcs.SetResult(null); // unblock DisposeAsync only after StartAsync completed await startTask.OrTimeout(); releaseDisposeTcs.SetResult(null); await disposeTask.OrTimeout(); transport.Verify(t => t.StartAsync(It.IsAny <Uri>(), It.IsAny <Channel <byte[], SendMessage> >(), It.IsAny <TransferMode>(), It.IsAny <string>()), Times.Never); }
public async Task CanStartConnectionWithoutSettingTransferModeFeature() { 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(IsNegotiateRequest(request) ? ResponseUtils.CreateResponse(HttpStatusCode.OK, ResponseUtils.CreateNegotiationResponse()) : ResponseUtils.CreateResponse(HttpStatusCode.OK)); }); var mockTransport = new Mock <ITransport>(); Channel <byte[], SendMessage> channel = null; mockTransport.Setup(t => t.StartAsync(It.IsAny <Uri>(), It.IsAny <Channel <byte[], SendMessage> >(), It.IsAny <TransferMode>(), It.IsAny <string>())) .Returns <Uri, Channel <byte[], SendMessage>, TransferMode, string>((url, c, transferMode, connectionId) => { channel = c; return(Task.CompletedTask); }); mockTransport.Setup(t => t.StopAsync()) .Returns(() => { channel.Writer.TryComplete(); return(Task.CompletedTask); }); mockTransport.SetupGet(t => t.Mode).Returns(TransferMode.Binary); var connection = new HttpConnection(new Uri("http://fakeuri.org/"), new TestTransportFactory(mockTransport.Object), loggerFactory: null, httpOptions: new HttpOptions { HttpMessageHandler = mockHttpHandler.Object }); await connection.StartAsync().OrTimeout(); var transferModeFeature = connection.Features.Get <ITransferModeFeature>(); await connection.DisposeAsync().OrTimeout(); mockTransport.Verify(t => t.StartAsync( It.IsAny <Uri>(), It.IsAny <Channel <byte[], SendMessage> >(), TransferMode.Text, It.IsAny <string>()), Times.Once); Assert.NotNull(transferModeFeature); Assert.Equal(TransferMode.Binary, transferModeFeature.TransferMode); }
public async Task ConnectionCanSendAndReceiveDifferentMessageSizesWebSocketsTransport(int length) { var message = new string('A', length); using (StartServer <Startup>(out var server)) { var logger = LoggerFactory.CreateLogger <EndToEndTests>(); var url = server.Url + "/echo"; var connection = new HttpConnection(new Uri(url), HttpTransportType.WebSockets, LoggerFactory); try { logger.LogInformation("Starting connection to {url}", url); await connection.StartAsync(TransferFormat.Binary).OrTimeout(); logger.LogInformation("Started connection to {url}", url); var bytes = Encoding.UTF8.GetBytes(message); logger.LogInformation("Sending {length} byte message", bytes.Length); await connection.Transport.Output.WriteAsync(bytes).OrTimeout(); logger.LogInformation("Sent message"); logger.LogInformation("Receiving message"); // Big timeout here because it can take a while to receive all the bytes var receivedData = await connection.Transport.Input.ReadAsync(bytes.Length).OrTimeout(TimeSpan.FromMinutes(2)); Assert.Equal(message, Encoding.UTF8.GetString(receivedData)); logger.LogInformation("Completed receive"); } catch (Exception ex) { logger.LogInformation(ex, "Test threw exception"); throw; } finally { logger.LogInformation("Disposing Connection"); await connection.DisposeAsync().OrTimeout(); logger.LogInformation("Disposed Connection"); } } }
/// <inheritdoc /> public async Task <ConnectionContext> ConnectAsync(TransferFormat transferFormat, CancellationToken cancellationToken = default) { var connection = new HttpConnection(_httpConnectionOptions, _loggerFactory); try { await connection.StartAsync(transferFormat, cancellationToken); return(connection); } catch { // Make sure the connection is disposed, in case it allocated any resources before failing. await connection.DisposeAsync(); throw; } }
public static async Task <int> ExecuteAsync(string baseUrl) { baseUrl = string.IsNullOrEmpty(baseUrl) ? "http://localhost:5000/chat" : baseUrl; Console.WriteLine($"Connecting to {baseUrl}..."); var connectionOptions = new HttpConnectionOptions { Url = new Uri(baseUrl), DefaultTransferFormat = TransferFormat.Text, }; var connection = new HttpConnection(connectionOptions, loggerFactory: null); try { await connection.StartAsync(); Console.WriteLine($"Connected to {baseUrl}"); var shutdown = new TaskCompletionSource <object>(); Console.CancelKeyPress += (sender, a) => { a.Cancel = true; shutdown.TrySetResult(null); }; _ = ReceiveLoop(Console.Out, connection.Transport.Input); _ = SendLoop(Console.In, connection.Transport.Output); await shutdown.Task; } catch (AggregateException aex) when(aex.InnerExceptions.All(e => e is OperationCanceledException)) { } catch (OperationCanceledException) { } finally { await connection.DisposeAsync(); } return(0); }
public async Task CanSendData() { var data = new byte[] { 1, 1, 2, 3, 5, 8 }; var sendTcs = new TaskCompletionSource <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 (IsNegotiateRequest(request)) { return(ResponseUtils.CreateResponse(HttpStatusCode.OK, ResponseUtils.CreateNegotiationResponse())); } if (request.Method == HttpMethod.Post) { sendTcs.SetResult(await request.Content.ReadAsByteArrayAsync()); } return(ResponseUtils.CreateResponse(HttpStatusCode.OK)); }); var connection = new HttpConnection(new Uri("http://fakeuri.org/"), TransportType.LongPolling, loggerFactory: null, httpOptions: new HttpOptions { HttpMessageHandler = mockHttpHandler.Object }); try { await connection.StartAsync(); await connection.SendAsync(data); Assert.Equal(data, await sendTcs.Task.OrTimeout()); } finally { await connection.DisposeAsync(); } }
public async Task query(string requested, string expectedNegotiate) { 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(); Assert.Equal(expectedNegotiate, request.RequestUri.ToString()); return(ResponseUtils.CreateResponse(HttpStatusCode.OK, ResponseUtils.CreateNegotiationResponse())); }); var connection = new HttpConnection(new Uri(requested), TransportType.LongPolling, loggerFactory: null, httpMessageHandler: mockHttpHandler.Object); await connection.StartAsync().OrTimeout(); await connection.DisposeAsync().OrTimeout(); }
public async Task CannotSendAfterReceiveThrewException() { 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.Get ? ResponseUtils.CreateResponse(HttpStatusCode.InternalServerError) : request.Method == HttpMethod.Options ? ResponseUtils.CreateResponse(HttpStatusCode.OK, ResponseUtils.CreateNegotiationResponse()) : ResponseUtils.CreateResponse(HttpStatusCode.OK)); }); var connection = new HttpConnection(new Uri("http://fakeuri.org/"), TransportType.LongPolling, loggerFactory: null, httpMessageHandler: mockHttpHandler.Object); try { var closeTcs = new TaskCompletionSource <Exception>(); connection.Closed += e => { closeTcs.TrySetResult(e); return(Task.CompletedTask); }; await connection.StartAsync(); // Exception in send should shutdown the connection await closeTcs.Task.OrTimeout(); var exception = await Assert.ThrowsAsync <InvalidOperationException>( async() => await connection.SendAsync(new byte[0])); Assert.Equal("Cannot send messages when the connection is not in the Connected state.", exception.Message); } finally { await connection.DisposeAsync(); } }
public async Task HttpConnectionThrowsIfSkipNegotiationSetAndTransportIsNotWebSockets(HttpTransportType transportType) { using (StartServer <Startup>(out var server)) { var logger = LoggerFactory.CreateLogger <EndToEndTests>(); var url = server.Url + "/echo"; var mockHttpHandler = new Mock <HttpMessageHandler>(); mockHttpHandler.Protected() .Setup <Task <HttpResponseMessage> >("SendAsync", ItExpr.IsAny <HttpRequestMessage>(), ItExpr.IsAny <CancellationToken>()) .Returns <HttpRequestMessage, CancellationToken>( (request, cancellationToken) => Task.FromException <HttpResponseMessage>(new InvalidOperationException("HTTP requests should not be sent."))); var httpOptions = new HttpConnectionOptions { Url = new Uri(url), Transports = transportType, SkipNegotiation = true, HttpMessageHandlerFactory = (httpMessageHandler) => mockHttpHandler.Object }; var connection = new HttpConnection(httpOptions, LoggerFactory); try { var exception = await Assert.ThrowsAsync <InvalidOperationException>(() => connection.StartAsync(TransferFormat.Binary).OrTimeout()); Assert.Equal("Negotiation can only be skipped when using the WebSocket transport directly.", exception.Message); } catch (Exception ex) { logger.LogInformation(ex, "Test threw exception"); throw; } finally { await connection.DisposeAsync().OrTimeout(); } } }
/// <summary> /// Creates a new connection to an <see cref="UriEndPoint"/>. /// </summary> /// <param name="endPoint">The <see cref="UriEndPoint"/> to connect to.</param> /// <param name="cancellationToken">The token to monitor for cancellation requests. The default value is <see cref="CancellationToken.None" />.</param> /// <returns> /// A <see cref="ValueTask{TResult}" /> that represents the asynchronous connect, yielding the <see cref="ConnectionContext" /> for the new connection when completed. /// </returns> public async ValueTask <ConnectionContext> ConnectAsync(EndPoint endPoint, CancellationToken cancellationToken = default) { if (endPoint == null) { throw new ArgumentNullException(nameof(endPoint)); } if (!(endPoint is UriEndPoint uriEndPoint)) { throw new NotSupportedException($"The provided {nameof(EndPoint)} must be of type {nameof(UriEndPoint)}."); } if (_httpConnectionOptions.Url != null && _httpConnectionOptions.Url != uriEndPoint.Uri) { throw new InvalidOperationException($"If {nameof(HttpConnectionOptions)}.{nameof(HttpConnectionOptions.Url)} was set, it must match the {nameof(UriEndPoint)}.{nameof(UriEndPoint.Uri)} passed to {nameof(ConnectAsync)}."); } // Shallow copy before setting the Url property so we don't mutate the user-defined options object. var shallowCopiedOptions = ShallowCopyHttpConnectionOptions(_httpConnectionOptions); shallowCopiedOptions.Url = uriEndPoint.Uri; var connection = new HttpConnection(shallowCopiedOptions, _loggerFactory); try { await connection.StartAsync(cancellationToken); return(connection); } catch { // Make sure the connection is disposed, in case it allocated any resources before failing. await connection.DisposeAsync(); throw; } }
public async Task TransportThatFallsbackCreatesNewConnection() { bool ExpectedErrors(WriteContext writeContext) { return(writeContext.LoggerName == typeof(HttpConnection).FullName && writeContext.EventId.Name == "ErrorStartingTransport"); } using (StartServer <Startup>(out var server, expectedErrorsFilter: ExpectedErrors)) { var url = server.Url + "/echo"; // The test should connect to the server using WebSockets transport on Windows 8 and newer. // On Windows 7/2008R2 it should use ServerSentEvents transport to connect to the server. // The test logic lives in the TestTransportFactory and FakeTransport. var connection = new HttpConnection(new HttpConnectionOptions { Url = new Uri(url) }, LoggerFactory, new TestTransportFactory()); await connection.StartAsync(TransferFormat.Text).OrTimeout(); await connection.DisposeAsync().OrTimeout(); } }
public async Task ClosedEventRaisedWhenConnectionToServerLost() { 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.Get ? ResponseUtils.CreateResponse(HttpStatusCode.InternalServerError) : request.Method == HttpMethod.Options ? ResponseUtils.CreateResponse(HttpStatusCode.OK, ResponseUtils.CreateNegotiationResponse()) : ResponseUtils.CreateResponse(HttpStatusCode.OK)); }); var connection = new HttpConnection(new Uri("http://fakeuri.org/"), TransportType.LongPolling, loggerFactory: null, httpMessageHandler: mockHttpHandler.Object); var closedEventTcs = new TaskCompletionSource <Exception>(); connection.Closed += e => { closedEventTcs.TrySetResult(e); return(Task.CompletedTask); }; try { await connection.StartAsync(); Assert.IsType <HttpRequestException>(await closedEventTcs.Task.OrTimeout()); } finally { await connection.DisposeAsync(); } }
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(IsNegotiateRequest(request) ? ResponseUtils.CreateResponse(HttpStatusCode.OK, ResponseUtils.CreateNegotiationResponse()) : ResponseUtils.CreateResponse(HttpStatusCode.OK)); }); using (var httpClient = new HttpClient(mockHttpHandler.Object)) { var longPollingTransport = new LongPollingTransport(httpClient, null, new LoggerFactory()); var connection = new HttpConnection(new Uri("http://fakeuri.org/"), new TestTransportFactory(longPollingTransport), loggerFactory: null, httpOptions: new HttpOptions { HttpMessageHandler = mockHttpHandler.Object }); try { await connection.StartAsync(); Assert.False(longPollingTransport.Running.IsCompleted); } finally { await connection.DisposeAsync(); } await longPollingTransport.Running.OrTimeout(); } }