public async Task EventQueueTimeout() { using (StartLog(out var loggerFactory)) { var logger = loggerFactory.CreateLogger <HttpConnectionTests>(); var testTransport = new TestTransport(); await WithConnectionAsync( CreateConnection(transport : testTransport), async (connection, closed) => { var onReceived = new SyncPoint(); connection.OnReceived(_ => onReceived.WaitToContinue().OrTimeout()); logger.LogInformation("Starting connection"); await connection.StartAsync().OrTimeout(); logger.LogInformation("Started connection"); await testTransport.Application.Output.WriteAsync(new byte[] { 1 }); await onReceived.WaitForSyncPoint().OrTimeout(); // Dispose should complete, even though the receive callbacks are completely blocked up. logger.LogInformation("Disposing connection"); await connection.DisposeAsync().OrTimeout(TimeSpan.FromSeconds(10)); logger.LogInformation("Disposed connection"); // Clear up blocked tasks. onReceived.Continue(); }); } }
public Task StartAsyncTransferFormatOverridesOptions() { var transport = new TestTransport(); return(WithConnectionAsync( CreateConnection(transport: transport, transferFormat: TransferFormat.Binary), async(connection) => { await connection.StartAsync(TransferFormat.Text).DefaultTimeout(); Assert.Equal(TransferFormat.Text, transport.Format); })); }
public async Task StartAsyncSetsTransferModeFeature() { var testTransport = new TestTransport(transferMode: TransferMode.Binary); await WithConnectionAsync( CreateConnection(transport : testTransport), async (connection, closed) => { Assert.Null(connection.Features.Get <ITransferModeFeature>()); await connection.StartAsync().OrTimeout(); var transferModeFeature = connection.Features.Get <ITransferModeFeature>(); Assert.NotNull(transferModeFeature); Assert.Equal(TransferMode.Binary, transferModeFeature.TransferMode); }); }
public Task TransportIsShutDownAfterDispose() { var transport = new TestTransport(); return(WithConnectionAsync( CreateConnection(transport: transport), async(connection) => { await connection.StartAsync().DefaultTimeout(); await connection.DisposeAsync().DefaultTimeout(); // This will throw OperationCanceledException if it's forcibly terminated // which we don't want await transport.Receiving.DefaultTimeout(); })); }
public async Task ConnectionClosedWhenTransportFails() { var testTransport = new TestTransport(); var expected = new Exception("Whoops!"); await WithConnectionAsync( CreateConnection(transport : testTransport), async (connection, closed) => { await connection.StartAsync().OrTimeout(); testTransport.Application.Writer.TryComplete(expected); var actual = await Assert.ThrowsAsync <Exception>(() => closed.OrTimeout()); Assert.Same(expected, actual); var sendException = await Assert.ThrowsAsync <InvalidOperationException>(() => connection.SendAsync(new byte[0]).OrTimeout()); Assert.Equal("Cannot send messages when the connection is not in the Connected state.", sendException.Message); }); }
public async Task EventsAreNotRunningOnMainLoop() { var testTransport = new TestTransport(); await WithConnectionAsync( CreateConnection(transport : testTransport), async (connection, closed) => { // Block up the OnReceived callback until we finish the test. var onReceived = new SyncPoint(); connection.OnReceived(_ => onReceived.WaitToContinue().OrTimeout()); await connection.StartAsync().OrTimeout(); // This will trigger the received callback await testTransport.Application.Output.WriteAsync(new byte[] { 1 }); // Wait to hit the sync point. We are now blocking up the TaskQueue await onReceived.WaitForSyncPoint().OrTimeout(); // Now we write something else and we want to test that the HttpConnection receive loop is still // removing items from the channel even though OnReceived is blocked up. await testTransport.Application.Output.WriteAsync(new byte[] { 1 }); // Now that we've written, we wait for WaitToReadAsync to return an INCOMPLETE task. It will do so // once HttpConnection reads the message. We also use a CTS to timeout in case the loop is indeed blocked var cts = new CancellationTokenSource(); cts.CancelAfter(TimeSpan.FromSeconds(5)); while (testTransport.Application.Input.WaitToReadAsync().IsCompleted&& !cts.IsCancellationRequested) { // Yield to allow the HttpConnection to dequeue the message await Task.Yield(); } // If we exited because we were cancelled, throw. cts.Token.ThrowIfCancellationRequested(); // We're free! Unblock onreceived onReceived.Continue(); }); }
public async Task TransportIsStoppedWhenConnectionIsDisposed() { var testHttpHandler = new TestHttpMessageHandler(); using (var httpClient = new HttpClient(testHttpHandler)) { var testTransport = new TestTransport(); await WithConnectionAsync( CreateConnection(transport : testTransport), async (connection) => { // Start the transport await connection.StartAsync(TransferFormat.Text).OrTimeout(); Assert.NotNull(testTransport.Receiving); Assert.False(testTransport.Receiving.IsCompleted); // Stop the connection, and we should stop the transport await connection.DisposeAsync().OrTimeout(); await testTransport.Receiving.OrTimeout(); }); } }