From 83139d36f4c7c97019b5738c747ac51af75c9357 Mon Sep 17 00:00:00 2001 From: BrennanConroy Date: Wed, 31 Oct 2018 16:05:26 -0700 Subject: [PATCH] Add some missing test logging (#3242) --- .../HttpConnectionManagerTests.cs | 446 ++++++++++-------- .../LongPollingTests.cs | 107 +++-- .../ServerSentEventsTests.cs | 126 +++-- .../WebSocketsTests.cs | 12 +- 4 files changed, 389 insertions(+), 302 deletions(-) diff --git a/test/Microsoft.AspNetCore.Http.Connections.Tests/HttpConnectionManagerTests.cs b/test/Microsoft.AspNetCore.Http.Connections.Tests/HttpConnectionManagerTests.cs index 871d76e0bf..62dfc89009 100644 --- a/test/Microsoft.AspNetCore.Http.Connections.Tests/HttpConnectionManagerTests.cs +++ b/test/Microsoft.AspNetCore.Http.Connections.Tests/HttpConnectionManagerTests.cs @@ -7,27 +7,37 @@ using System.IO.Pipelines; using System.Threading.Tasks; using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Http.Connections.Internal; +using Microsoft.AspNetCore.SignalR.Tests; using Microsoft.Extensions.Logging; using Xunit; +using Xunit.Abstractions; namespace Microsoft.AspNetCore.Http.Connections.Tests { - public class HttpConnectionManagerTests + public class HttpConnectionManagerTests : VerifiableLoggedTest { + public HttpConnectionManagerTests(ITestOutputHelper output) + : base(output) + { + } + [Fact] public void NewConnectionsHaveConnectionId() { - var connectionManager = CreateConnectionManager(); - var connection = connectionManager.CreateConnection(); + using (StartVerifiableLog(out var loggerFactory)) + { + var connectionManager = CreateConnectionManager(loggerFactory); + var connection = connectionManager.CreateConnection(); - Assert.NotNull(connection.ConnectionId); - Assert.Equal(HttpConnectionStatus.Inactive, connection.Status); - Assert.Null(connection.ApplicationTask); - Assert.Null(connection.TransportTask); - Assert.Null(connection.Cancellation); - Assert.NotEqual(default, connection.LastSeenUtc); - Assert.NotNull(connection.Transport); - Assert.NotNull(connection.Application); + Assert.NotNull(connection.ConnectionId); + Assert.Equal(HttpConnectionStatus.Inactive, connection.Status); + Assert.Null(connection.ApplicationTask); + Assert.Null(connection.TransportTask); + Assert.Null(connection.Cancellation); + Assert.NotEqual(default, connection.LastSeenUtc); + Assert.NotNull(connection.Transport); + Assert.NotNull(connection.Application); + } } [Theory] @@ -42,305 +52,341 @@ namespace Microsoft.AspNetCore.Http.Connections.Tests [InlineData(ConnectionStates.CloseGracefully | ConnectionStates.ApplicationFaulted | ConnectionStates.TransportNotFaulted)] public async Task DisposingConnectionsClosesBothSidesOfThePipe(ConnectionStates states) { - var closeGracefully = (states & ConnectionStates.CloseGracefully) != 0; - var applicationFaulted = (states & ConnectionStates.ApplicationFaulted) != 0; - var transportFaulted = (states & ConnectionStates.TransportFaulted) != 0; - - var connectionManager = CreateConnectionManager(); - var connection = connectionManager.CreateConnection(); - - if (applicationFaulted) + using (StartVerifiableLog(out var loggerFactory)) { - // If the application is faulted then we want to make sure the transport task only completes after - // the application completes - connection.ApplicationTask = Task.FromException(new Exception("Application failed")); - connection.TransportTask = Task.Run(async () => - { - // Wait for the application to end - var result = await connection.Application.Input.ReadAsync(); - connection.Application.Input.AdvanceTo(result.Buffer.End); + var closeGracefully = (states & ConnectionStates.CloseGracefully) != 0; + var applicationFaulted = (states & ConnectionStates.ApplicationFaulted) != 0; + var transportFaulted = (states & ConnectionStates.TransportFaulted) != 0; - if (transportFaulted) + var connectionManager = CreateConnectionManager(loggerFactory); + var connection = connectionManager.CreateConnection(); + + if (applicationFaulted) + { + // If the application is faulted then we want to make sure the transport task only completes after + // the application completes + connection.ApplicationTask = Task.FromException(new Exception("Application failed")); + connection.TransportTask = Task.Run(async () => { - throw new Exception("Transport failed"); - } - }); + // Wait for the application to end + var result = await connection.Application.Input.ReadAsync(); + connection.Application.Input.AdvanceTo(result.Buffer.End); - } - else if (transportFaulted) - { - // If the transport is faulted then we want to make sure the transport task only completes after - // the application completes - connection.TransportTask = Task.FromException(new Exception("Application failed")); - connection.ApplicationTask = Task.Run(async () => + if (transportFaulted) + { + throw new Exception("Transport failed"); + } + }); + + } + else if (transportFaulted) { - // Wait for the application to end - var result = await connection.Transport.Input.ReadAsync(); - connection.Transport.Input.AdvanceTo(result.Buffer.End); - }); - } - else - { - connection.ApplicationTask = Task.CompletedTask; - connection.TransportTask = Task.CompletedTask; - } + // If the transport is faulted then we want to make sure the transport task only completes after + // the application completes + connection.TransportTask = Task.FromException(new Exception("Application failed")); + connection.ApplicationTask = Task.Run(async () => + { + // Wait for the application to end + var result = await connection.Transport.Input.ReadAsync(); + connection.Transport.Input.AdvanceTo(result.Buffer.End); + }); + } + else + { + connection.ApplicationTask = Task.CompletedTask; + connection.TransportTask = Task.CompletedTask; + } - var applicationInputTcs = new TaskCompletionSource(); - var applicationOutputTcs = new TaskCompletionSource(); - var transportInputTcs = new TaskCompletionSource(); - var transportOutputTcs = new TaskCompletionSource(); + var applicationInputTcs = new TaskCompletionSource(); + var applicationOutputTcs = new TaskCompletionSource(); + var transportInputTcs = new TaskCompletionSource(); + var transportOutputTcs = new TaskCompletionSource(); - connection.Transport.Input.OnWriterCompleted((_, __) => transportInputTcs.TrySetResult(null), null); - connection.Transport.Output.OnReaderCompleted((_, __) => transportOutputTcs.TrySetResult(null), null); - connection.Application.Input.OnWriterCompleted((_, __) => applicationInputTcs.TrySetResult(null), null); - connection.Application.Output.OnReaderCompleted((_, __) => applicationOutputTcs.TrySetResult(null), null); + connection.Transport.Input.OnWriterCompleted((_, __) => transportInputTcs.TrySetResult(null), null); + connection.Transport.Output.OnReaderCompleted((_, __) => transportOutputTcs.TrySetResult(null), null); + connection.Application.Input.OnWriterCompleted((_, __) => applicationInputTcs.TrySetResult(null), null); + connection.Application.Output.OnReaderCompleted((_, __) => applicationOutputTcs.TrySetResult(null), null); - try - { - await connection.DisposeAsync(closeGracefully).OrTimeout(); + try + { + await connection.DisposeAsync(closeGracefully).OrTimeout(); + } + catch (Exception ex) when (!(ex is TimeoutException)) + { + // Ignore the exception that bubbles out of the failing task + } + + await Task.WhenAll(applicationInputTcs.Task, applicationOutputTcs.Task, transportInputTcs.Task, transportOutputTcs.Task).OrTimeout(); } - catch (Exception ex) when (!(ex is TimeoutException)) - { - // Ignore the exception that bubbles out of the failing task - } - - await Task.WhenAll(applicationInputTcs.Task, applicationOutputTcs.Task, transportInputTcs.Task, transportOutputTcs.Task).OrTimeout(); } [Fact] public void NewConnectionsCanBeRetrieved() { - var connectionManager = CreateConnectionManager(); - var connection = connectionManager.CreateConnection(); + using (StartVerifiableLog(out var loggerFactory)) + { + var connectionManager = CreateConnectionManager(loggerFactory); + var connection = connectionManager.CreateConnection(); - Assert.NotNull(connection.ConnectionId); + Assert.NotNull(connection.ConnectionId); - Assert.True(connectionManager.TryGetConnection(connection.ConnectionId, out var newConnection)); - Assert.Same(newConnection, connection); + Assert.True(connectionManager.TryGetConnection(connection.ConnectionId, out var newConnection)); + Assert.Same(newConnection, connection); + } } [Fact] public void AddNewConnection() { - var connectionManager = CreateConnectionManager(); - var connection = connectionManager.CreateConnection(PipeOptions.Default, PipeOptions.Default); + using (StartVerifiableLog(out var loggerFactory)) + { + var connectionManager = CreateConnectionManager(loggerFactory); + var connection = connectionManager.CreateConnection(PipeOptions.Default, PipeOptions.Default); - var transport = connection.Transport; + var transport = connection.Transport; - Assert.NotNull(connection.ConnectionId); - Assert.NotNull(transport); + Assert.NotNull(connection.ConnectionId); + Assert.NotNull(transport); - Assert.True(connectionManager.TryGetConnection(connection.ConnectionId, out var newConnection)); - Assert.Same(newConnection, connection); - Assert.Same(transport, newConnection.Transport); + Assert.True(connectionManager.TryGetConnection(connection.ConnectionId, out var newConnection)); + Assert.Same(newConnection, connection); + Assert.Same(transport, newConnection.Transport); + } } [Fact] public void RemoveConnection() { - var connectionManager = CreateConnectionManager(); - var connection = connectionManager.CreateConnection(PipeOptions.Default, PipeOptions.Default); + using (StartVerifiableLog(out var loggerFactory)) + { + var connectionManager = CreateConnectionManager(loggerFactory); + var connection = connectionManager.CreateConnection(PipeOptions.Default, PipeOptions.Default); - var transport = connection.Transport; + var transport = connection.Transport; - Assert.NotNull(connection.ConnectionId); - Assert.NotNull(transport); + Assert.NotNull(connection.ConnectionId); + Assert.NotNull(transport); - Assert.True(connectionManager.TryGetConnection(connection.ConnectionId, out var newConnection)); - Assert.Same(newConnection, connection); - Assert.Same(transport, newConnection.Transport); + Assert.True(connectionManager.TryGetConnection(connection.ConnectionId, out var newConnection)); + Assert.Same(newConnection, connection); + Assert.Same(transport, newConnection.Transport); - connectionManager.RemoveConnection(connection.ConnectionId); - Assert.False(connectionManager.TryGetConnection(connection.ConnectionId, out newConnection)); + connectionManager.RemoveConnection(connection.ConnectionId); + Assert.False(connectionManager.TryGetConnection(connection.ConnectionId, out newConnection)); + } } [Fact] public async Task CloseConnectionsEndsAllPendingConnections() { - var connectionManager = CreateConnectionManager(); - var connection = connectionManager.CreateConnection(PipeOptions.Default, PipeOptions.Default); - - connection.ApplicationTask = Task.Run(async () => + using (StartVerifiableLog(out var loggerFactory)) { - var result = await connection.Transport.Input.ReadAsync(); + var connectionManager = CreateConnectionManager(loggerFactory); + var connection = connectionManager.CreateConnection(PipeOptions.Default, PipeOptions.Default); - try + connection.ApplicationTask = Task.Run(async () => { - Assert.True(result.IsCompleted); + var result = await connection.Transport.Input.ReadAsync(); - // We should be able to write - await connection.Transport.Output.WriteAsync(new byte[] { 1 }); - } - finally - { - connection.Transport.Input.AdvanceTo(result.Buffer.End); - } - }); + try + { + Assert.True(result.IsCompleted); - connection.TransportTask = Task.Run(async () => - { - var result = await connection.Application.Input.ReadAsync(); - Assert.Equal(new byte[] { 1 }, result.Buffer.ToArray()); - connection.Application.Input.AdvanceTo(result.Buffer.End); + // We should be able to write + await connection.Transport.Output.WriteAsync(new byte[] { 1 }); + } + finally + { + connection.Transport.Input.AdvanceTo(result.Buffer.End); + } + }); - result = await connection.Application.Input.ReadAsync(); - try - { - Assert.True(result.IsCompleted); - } - finally + connection.TransportTask = Task.Run(async () => { + var result = await connection.Application.Input.ReadAsync(); + Assert.Equal(new byte[] { 1 }, result.Buffer.ToArray()); connection.Application.Input.AdvanceTo(result.Buffer.End); - } - }); - connectionManager.CloseConnections(); + result = await connection.Application.Input.ReadAsync(); + try + { + Assert.True(result.IsCompleted); + } + finally + { + connection.Application.Input.AdvanceTo(result.Buffer.End); + } + }); - await connection.DisposeAsync(); + connectionManager.CloseConnections(); + + await connection.DisposeAsync(); + } } [Fact] public async Task DisposingConnectionMultipleTimesWaitsOnConnectionClose() { - var connectionManager = CreateConnectionManager(); - var connection = connectionManager.CreateConnection(PipeOptions.Default, PipeOptions.Default); - var tcs = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); + using (StartVerifiableLog(out var loggerFactory)) + { + var connectionManager = CreateConnectionManager(loggerFactory); + var connection = connectionManager.CreateConnection(PipeOptions.Default, PipeOptions.Default); + var tcs = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); - connection.ApplicationTask = tcs.Task; - connection.TransportTask = tcs.Task; + connection.ApplicationTask = tcs.Task; + connection.TransportTask = tcs.Task; - var firstTask = connection.DisposeAsync(); - var secondTask = connection.DisposeAsync(); - Assert.False(firstTask.IsCompleted); - Assert.False(secondTask.IsCompleted); + var firstTask = connection.DisposeAsync(); + var secondTask = connection.DisposeAsync(); + Assert.False(firstTask.IsCompleted); + Assert.False(secondTask.IsCompleted); - tcs.TrySetResult(null); + tcs.TrySetResult(null); - await Task.WhenAll(firstTask, secondTask).OrTimeout(); + await Task.WhenAll(firstTask, secondTask).OrTimeout(); + } } [Fact] public async Task DisposingConnectionMultipleGetsExceptionFromTransportOrApp() { - var connectionManager = CreateConnectionManager(); - var connection = connectionManager.CreateConnection(PipeOptions.Default, PipeOptions.Default); - var tcs = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); + using (StartVerifiableLog(out var loggerFactory)) + { + var connectionManager = CreateConnectionManager(loggerFactory); + var connection = connectionManager.CreateConnection(PipeOptions.Default, PipeOptions.Default); + var tcs = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); - connection.ApplicationTask = tcs.Task; - connection.TransportTask = tcs.Task; + connection.ApplicationTask = tcs.Task; + connection.TransportTask = tcs.Task; - var firstTask = connection.DisposeAsync(); - var secondTask = connection.DisposeAsync(); - Assert.False(firstTask.IsCompleted); - Assert.False(secondTask.IsCompleted); + var firstTask = connection.DisposeAsync(); + var secondTask = connection.DisposeAsync(); + Assert.False(firstTask.IsCompleted); + Assert.False(secondTask.IsCompleted); - tcs.TrySetException(new InvalidOperationException("Error")); + tcs.TrySetException(new InvalidOperationException("Error")); - var exception = await Assert.ThrowsAsync(async () => await firstTask.OrTimeout()); - Assert.Equal("Error", exception.Message); + var exception = await Assert.ThrowsAsync(async () => await firstTask.OrTimeout()); + Assert.Equal("Error", exception.Message); - exception = await Assert.ThrowsAsync(async () => await secondTask.OrTimeout()); - Assert.Equal("Error", exception.Message); + exception = await Assert.ThrowsAsync(async () => await secondTask.OrTimeout()); + Assert.Equal("Error", exception.Message); + } } [Fact] public async Task DisposingConnectionMultipleGetsCancellation() { - var connectionManager = CreateConnectionManager(); - var connection = connectionManager.CreateConnection(PipeOptions.Default, PipeOptions.Default); - var tcs = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); + using (StartVerifiableLog(out var loggerFactory)) + { + var connectionManager = CreateConnectionManager(loggerFactory); + var connection = connectionManager.CreateConnection(PipeOptions.Default, PipeOptions.Default); + var tcs = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); - connection.ApplicationTask = tcs.Task; - connection.TransportTask = tcs.Task; + connection.ApplicationTask = tcs.Task; + connection.TransportTask = tcs.Task; - var firstTask = connection.DisposeAsync(); - var secondTask = connection.DisposeAsync(); - Assert.False(firstTask.IsCompleted); - Assert.False(secondTask.IsCompleted); + var firstTask = connection.DisposeAsync(); + var secondTask = connection.DisposeAsync(); + Assert.False(firstTask.IsCompleted); + Assert.False(secondTask.IsCompleted); - tcs.TrySetCanceled(); + tcs.TrySetCanceled(); - await Assert.ThrowsAsync(async () => await firstTask.OrTimeout()); - await Assert.ThrowsAsync(async () => await secondTask.OrTimeout()); + await Assert.ThrowsAsync(async () => await firstTask.OrTimeout()); + await Assert.ThrowsAsync(async () => await secondTask.OrTimeout()); + } } [Fact] public async Task DisposeInactiveConnection() { - var connectionManager = CreateConnectionManager(); - var connection = connectionManager.CreateConnection(PipeOptions.Default, PipeOptions.Default); + using (StartVerifiableLog(out var loggerFactory)) + { + var connectionManager = CreateConnectionManager(loggerFactory); + var connection = connectionManager.CreateConnection(PipeOptions.Default, PipeOptions.Default); - Assert.NotNull(connection.ConnectionId); - Assert.NotNull(connection.Transport); + Assert.NotNull(connection.ConnectionId); + Assert.NotNull(connection.Transport); - await connection.DisposeAsync(); - Assert.Equal(HttpConnectionStatus.Disposed, connection.Status); + await connection.DisposeAsync(); + Assert.Equal(HttpConnectionStatus.Disposed, connection.Status); + } } [Fact] public async Task DisposeInactiveConnectionWithNoPipes() { - var connectionManager = CreateConnectionManager(); - var connection = connectionManager.CreateConnection(); + using (StartVerifiableLog(out var loggerFactory)) + { + var connectionManager = CreateConnectionManager(loggerFactory); + var connection = connectionManager.CreateConnection(); - Assert.NotNull(connection.ConnectionId); - Assert.NotNull(connection.Transport); - Assert.NotNull(connection.Application); + Assert.NotNull(connection.ConnectionId); + Assert.NotNull(connection.Transport); + Assert.NotNull(connection.Application); - await connection.DisposeAsync(); - Assert.Equal(HttpConnectionStatus.Disposed, connection.Status); + await connection.DisposeAsync(); + Assert.Equal(HttpConnectionStatus.Disposed, connection.Status); + } } [Fact] public async Task ApplicationLifetimeIsHookedUp() { - var appLifetime = new TestApplicationLifetime(); - var connectionManager = CreateConnectionManager(appLifetime); - var tcs = new TaskCompletionSource(); - - appLifetime.Start(); - - var connection = connectionManager.CreateConnection(PipeOptions.Default, PipeOptions.Default); - - connection.Application.Output.OnReaderCompleted((error, state) => + using (StartVerifiableLog(out var loggerFactory)) { - tcs.TrySetResult(null); - }, - null); + var appLifetime = new TestApplicationLifetime(); + var connectionManager = CreateConnectionManager(loggerFactory, appLifetime); + var tcs = new TaskCompletionSource(); - appLifetime.StopApplication(); + appLifetime.Start(); - // Connection should be disposed so this should complete immediately - await tcs.Task.OrTimeout(); + var connection = connectionManager.CreateConnection(PipeOptions.Default, PipeOptions.Default); + + connection.Application.Output.OnReaderCompleted((error, state) => + { + tcs.TrySetResult(null); + }, + null); + + appLifetime.StopApplication(); + + // Connection should be disposed so this should complete immediately + await tcs.Task.OrTimeout(); + } } [Fact] public async Task ApplicationLifetimeCanStartBeforeHttpConnectionManagerInitialized() { - var appLifetime = new TestApplicationLifetime(); - appLifetime.Start(); - - var connectionManager = CreateConnectionManager(appLifetime); - var tcs = new TaskCompletionSource(); - - var connection = connectionManager.CreateConnection(PipeOptions.Default, PipeOptions.Default); - - connection.Application.Output.OnReaderCompleted((error, state) => + using (StartVerifiableLog(out var loggerFactory)) { - tcs.TrySetResult(null); - }, - null); + var appLifetime = new TestApplicationLifetime(); + appLifetime.Start(); - appLifetime.StopApplication(); + var connectionManager = CreateConnectionManager(loggerFactory, appLifetime); + var tcs = new TaskCompletionSource(); - // Connection should be disposed so this should complete immediately - await tcs.Task.OrTimeout(); + var connection = connectionManager.CreateConnection(PipeOptions.Default, PipeOptions.Default); + + connection.Application.Output.OnReaderCompleted((error, state) => + { + tcs.TrySetResult(null); + }, + null); + + appLifetime.StopApplication(); + + // Connection should be disposed so this should complete immediately + await tcs.Task.OrTimeout(); + } } - private static HttpConnectionManager CreateConnectionManager(IApplicationLifetime lifetime = null) + private static HttpConnectionManager CreateConnectionManager(ILoggerFactory loggerFactory, IApplicationLifetime lifetime = null) { lifetime = lifetime ?? new EmptyApplicationLifetime(); - return new HttpConnectionManager(new LoggerFactory(), lifetime); + return new HttpConnectionManager(loggerFactory, lifetime); } [Flags] diff --git a/test/Microsoft.AspNetCore.Http.Connections.Tests/LongPollingTests.cs b/test/Microsoft.AspNetCore.Http.Connections.Tests/LongPollingTests.cs index ed6cdc4e60..69c471d72c 100644 --- a/test/Microsoft.AspNetCore.Http.Connections.Tests/LongPollingTests.cs +++ b/test/Microsoft.AspNetCore.Http.Connections.Tests/LongPollingTests.cs @@ -9,92 +9,111 @@ using System.Threading; using System.Threading.Tasks; using Microsoft.AspNetCore.Connections; using Microsoft.AspNetCore.Http.Connections.Internal.Transports; +using Microsoft.AspNetCore.SignalR.Tests; using Microsoft.Extensions.Logging; using Xunit; +using Xunit.Abstractions; namespace Microsoft.AspNetCore.Http.Connections.Tests { - public class LongPollingTests + public class LongPollingTests : VerifiableLoggedTest { + public LongPollingTests(ITestOutputHelper output) + : base(output) + { + } + [Fact] public async Task Set204StatusCodeWhenChannelComplete() { - var pair = DuplexPipe.CreateConnectionPair(PipeOptions.Default, PipeOptions.Default); - var connection = new DefaultConnectionContext("foo", pair.Transport, pair.Application); + using (StartVerifiableLog(out var loggerFactory)) + { + var pair = DuplexPipe.CreateConnectionPair(PipeOptions.Default, PipeOptions.Default); + var connection = new DefaultConnectionContext("foo", pair.Transport, pair.Application); - var context = new DefaultHttpContext(); + var context = new DefaultHttpContext(); - var poll = new LongPollingTransport(CancellationToken.None, connection.Application.Input, loggerFactory: new LoggerFactory()); + var poll = new LongPollingTransport(CancellationToken.None, connection.Application.Input, loggerFactory); - connection.Transport.Output.Complete(); + connection.Transport.Output.Complete(); - await poll.ProcessRequestAsync(context, context.RequestAborted).OrTimeout(); + await poll.ProcessRequestAsync(context, context.RequestAborted).OrTimeout(); - Assert.Equal(204, context.Response.StatusCode); + Assert.Equal(204, context.Response.StatusCode); + } } [Fact] public async Task Set200StatusCodeWhenTimeoutTokenFires() { - var pair = DuplexPipe.CreateConnectionPair(PipeOptions.Default, PipeOptions.Default); - var connection = new DefaultConnectionContext("foo", pair.Transport, pair.Application); - var context = new DefaultHttpContext(); - - var timeoutToken = new CancellationToken(true); - var poll = new LongPollingTransport(timeoutToken, connection.Application.Input, loggerFactory: new LoggerFactory()); - - using (var cts = CancellationTokenSource.CreateLinkedTokenSource(timeoutToken, context.RequestAborted)) + using (StartVerifiableLog(out var loggerFactory)) { - await poll.ProcessRequestAsync(context, cts.Token).OrTimeout(); + var pair = DuplexPipe.CreateConnectionPair(PipeOptions.Default, PipeOptions.Default); + var connection = new DefaultConnectionContext("foo", pair.Transport, pair.Application); + var context = new DefaultHttpContext(); - Assert.Equal(0, context.Response.ContentLength); - Assert.Equal(200, context.Response.StatusCode); + var timeoutToken = new CancellationToken(true); + var poll = new LongPollingTransport(timeoutToken, connection.Application.Input, loggerFactory); + + using (var cts = CancellationTokenSource.CreateLinkedTokenSource(timeoutToken, context.RequestAborted)) + { + await poll.ProcessRequestAsync(context, cts.Token).OrTimeout(); + + Assert.Equal(0, context.Response.ContentLength); + Assert.Equal(200, context.Response.StatusCode); + } } } [Fact] public async Task FrameSentAsSingleResponse() { - var pair = DuplexPipe.CreateConnectionPair(PipeOptions.Default, PipeOptions.Default); - var connection = new DefaultConnectionContext("foo", pair.Transport, pair.Application); - var context = new DefaultHttpContext(); + using (StartVerifiableLog(out var loggerFactory)) + { + 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; + var poll = new LongPollingTransport(CancellationToken.None, connection.Application.Input, loggerFactory); + var ms = new MemoryStream(); + context.Response.Body = ms; - await connection.Transport.Output.WriteAsync(Encoding.UTF8.GetBytes("Hello World")); - connection.Transport.Output.Complete(); + await connection.Transport.Output.WriteAsync(Encoding.UTF8.GetBytes("Hello World")); + connection.Transport.Output.Complete(); - await poll.ProcessRequestAsync(context, context.RequestAborted).OrTimeout(); + await poll.ProcessRequestAsync(context, context.RequestAborted).OrTimeout(); - Assert.Equal(200, context.Response.StatusCode); - Assert.Equal("Hello World", Encoding.UTF8.GetString(ms.ToArray())); + Assert.Equal(200, context.Response.StatusCode); + Assert.Equal("Hello World", Encoding.UTF8.GetString(ms.ToArray())); + } } [Fact] 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(); + using (StartVerifiableLog(out var loggerFactory)) + { + 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; + var poll = new LongPollingTransport(CancellationToken.None, connection.Application.Input, 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")); + 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(); + connection.Transport.Output.Complete(); - await poll.ProcessRequestAsync(context, context.RequestAborted).OrTimeout(); + await poll.ProcessRequestAsync(context, context.RequestAborted).OrTimeout(); - Assert.Equal(200, context.Response.StatusCode); + Assert.Equal(200, context.Response.StatusCode); - var payload = ms.ToArray(); - Assert.Equal("Hello World", Encoding.UTF8.GetString(payload)); + var payload = ms.ToArray(); + Assert.Equal("Hello World", Encoding.UTF8.GetString(payload)); + } } [Fact] diff --git a/test/Microsoft.AspNetCore.Http.Connections.Tests/ServerSentEventsTests.cs b/test/Microsoft.AspNetCore.Http.Connections.Tests/ServerSentEventsTests.cs index ab0863c5e4..72c0ec3103 100644 --- a/test/Microsoft.AspNetCore.Http.Connections.Tests/ServerSentEventsTests.cs +++ b/test/Microsoft.AspNetCore.Http.Connections.Tests/ServerSentEventsTests.cs @@ -11,85 +11,104 @@ using Microsoft.AspNetCore.Http.Features; using Microsoft.AspNetCore.Http.Connections.Internal.Transports; using Microsoft.Extensions.Logging; using Xunit; +using Microsoft.AspNetCore.SignalR.Tests; +using Xunit.Abstractions; namespace Microsoft.AspNetCore.Http.Connections.Tests { - public class ServerSentEventsTests + public class ServerSentEventsTests : VerifiableLoggedTest { + public ServerSentEventsTests(ITestOutputHelper output) + : base(output) + { + } + [Fact] public async Task SSESetsContentType() { - var pair = DuplexPipe.CreateConnectionPair(PipeOptions.Default, PipeOptions.Default); - var connection = new DefaultConnectionContext("foo", pair.Transport, pair.Application); - var context = new DefaultHttpContext(); + using (StartVerifiableLog(out var loggerFactory)) + { + var pair = DuplexPipe.CreateConnectionPair(PipeOptions.Default, PipeOptions.Default); + var connection = new DefaultConnectionContext("foo", pair.Transport, pair.Application); + var context = new DefaultHttpContext(); - var sse = new ServerSentEventsTransport(connection.Application.Input, connectionId: string.Empty, loggerFactory: new LoggerFactory()); + var sse = new ServerSentEventsTransport(connection.Application.Input, connectionId: string.Empty, loggerFactory); - connection.Transport.Output.Complete(); + connection.Transport.Output.Complete(); - await sse.ProcessRequestAsync(context, context.RequestAborted); + await sse.ProcessRequestAsync(context, context.RequestAborted); - Assert.Equal("text/event-stream", context.Response.ContentType); - Assert.Equal("no-cache", context.Response.Headers["Cache-Control"]); + Assert.Equal("text/event-stream", context.Response.ContentType); + Assert.Equal("no-cache", context.Response.Headers["Cache-Control"]); + } } [Fact] public async Task SSETurnsResponseBufferingOff() { - var pair = DuplexPipe.CreateConnectionPair(PipeOptions.Default, PipeOptions.Default); - var connection = new DefaultConnectionContext("foo", pair.Transport, pair.Application); - var context = new DefaultHttpContext(); + using (StartVerifiableLog(out var loggerFactory)) + { + var pair = DuplexPipe.CreateConnectionPair(PipeOptions.Default, PipeOptions.Default); + var connection = new DefaultConnectionContext("foo", pair.Transport, pair.Application); + var context = new DefaultHttpContext(); - var feature = new HttpBufferingFeature(); - context.Features.Set(feature); - var sse = new ServerSentEventsTransport(connection.Application.Input, connectionId: connection.ConnectionId, loggerFactory: new LoggerFactory()); + var feature = new HttpBufferingFeature(); + context.Features.Set(feature); + var sse = new ServerSentEventsTransport(connection.Application.Input, connectionId: connection.ConnectionId, loggerFactory); - connection.Transport.Output.Complete(); + connection.Transport.Output.Complete(); - await sse.ProcessRequestAsync(context, context.RequestAborted); + await sse.ProcessRequestAsync(context, context.RequestAborted); - Assert.True(feature.ResponseBufferingDisabled); + Assert.True(feature.ResponseBufferingDisabled); + } } [Fact] public async Task SSEWritesMessages() { - var pair = DuplexPipe.CreateConnectionPair(PipeOptions.Default, new PipeOptions(readerScheduler: PipeScheduler.Inline)); - var connection = new DefaultConnectionContext("foo", pair.Transport, pair.Application); - var context = new DefaultHttpContext(); + using (StartVerifiableLog(out var loggerFactory)) + { + var pair = DuplexPipe.CreateConnectionPair(PipeOptions.Default, new PipeOptions(readerScheduler: PipeScheduler.Inline)); + var connection = new DefaultConnectionContext("foo", pair.Transport, pair.Application); + var context = new DefaultHttpContext(); - var ms = new MemoryStream(); - context.Response.Body = ms; - var sse = new ServerSentEventsTransport(connection.Application.Input, connectionId: string.Empty, loggerFactory: new LoggerFactory()); + var ms = new MemoryStream(); + context.Response.Body = ms; + var sse = new ServerSentEventsTransport(connection.Application.Input, connectionId: string.Empty, loggerFactory); - var task = sse.ProcessRequestAsync(context, context.RequestAborted); + var task = sse.ProcessRequestAsync(context, context.RequestAborted); - await connection.Transport.Output.WriteAsync(Encoding.ASCII.GetBytes("Hello")); - connection.Transport.Output.Complete(); - await task.OrTimeout(); - Assert.Equal(":\r\ndata: Hello\r\n\r\n", Encoding.ASCII.GetString(ms.ToArray())); + await connection.Transport.Output.WriteAsync(Encoding.ASCII.GetBytes("Hello")); + connection.Transport.Output.Complete(); + await task.OrTimeout(); + Assert.Equal(":\r\ndata: Hello\r\n\r\n", Encoding.ASCII.GetString(ms.ToArray())); + } } [Fact] public async Task SSEWritesVeryLargeMessages() { - var pair = DuplexPipe.CreateConnectionPair(PipeOptions.Default, new PipeOptions(readerScheduler: PipeScheduler.Inline)); - var connection = new DefaultConnectionContext("foo", pair.Transport, pair.Application); - var context = new DefaultHttpContext(); + using (StartVerifiableLog(out var loggerFactory)) + { + var pair = DuplexPipe.CreateConnectionPair(PipeOptions.Default, new PipeOptions(readerScheduler: PipeScheduler.Inline)); + var connection = new DefaultConnectionContext("foo", pair.Transport, pair.Application); + var context = new DefaultHttpContext(); - var ms = new MemoryStream(); - context.Response.Body = ms; - var sse = new ServerSentEventsTransport(connection.Application.Input, connectionId: string.Empty, loggerFactory: new LoggerFactory()); + var ms = new MemoryStream(); + context.Response.Body = ms; + var sse = new ServerSentEventsTransport(connection.Application.Input, connectionId: string.Empty, loggerFactory); - var task = sse.ProcessRequestAsync(context, context.RequestAborted); + var task = sse.ProcessRequestAsync(context, context.RequestAborted); - string hText = new string('H', 60000); - string wText = new string('W', 60000); + string hText = new string('H', 60000); + string wText = new string('W', 60000); - await connection.Transport.Output.WriteAsync(Encoding.ASCII.GetBytes(hText + wText)); - connection.Transport.Output.Complete(); - await task.OrTimeout(); - Assert.Equal(":\r\ndata: " + hText + wText + "\r\n\r\n", Encoding.ASCII.GetString(ms.ToArray())); + await connection.Transport.Output.WriteAsync(Encoding.ASCII.GetBytes(hText + wText)); + connection.Transport.Output.Complete(); + await task.OrTimeout(); + Assert.Equal(":\r\ndata: " + hText + wText + "\r\n\r\n", Encoding.ASCII.GetString(ms.ToArray())); + } } [Theory] @@ -98,21 +117,24 @@ namespace Microsoft.AspNetCore.Http.Connections.Tests [InlineData("Hello\r\nWorld", ":\r\ndata: Hello\r\ndata: World\r\n\r\n")] public async Task SSEAddsAppropriateFraming(string message, string expected) { - var pair = DuplexPipe.CreateConnectionPair(PipeOptions.Default, PipeOptions.Default); - var connection = new DefaultConnectionContext("foo", pair.Transport, pair.Application); - var context = new DefaultHttpContext(); + using (StartVerifiableLog(out var loggerFactory)) + { + var pair = DuplexPipe.CreateConnectionPair(PipeOptions.Default, PipeOptions.Default); + var connection = new DefaultConnectionContext("foo", pair.Transport, pair.Application); + var context = new DefaultHttpContext(); - var sse = new ServerSentEventsTransport(connection.Application.Input, connectionId: string.Empty, loggerFactory: new LoggerFactory()); - var ms = new MemoryStream(); - context.Response.Body = ms; + var sse = new ServerSentEventsTransport(connection.Application.Input, connectionId: string.Empty, loggerFactory); + var ms = new MemoryStream(); + context.Response.Body = ms; - await connection.Transport.Output.WriteAsync(Encoding.UTF8.GetBytes(message)); + await connection.Transport.Output.WriteAsync(Encoding.UTF8.GetBytes(message)); - connection.Transport.Output.Complete(); + connection.Transport.Output.Complete(); - await sse.ProcessRequestAsync(context, context.RequestAborted); + await sse.ProcessRequestAsync(context, context.RequestAborted); - Assert.Equal(expected, Encoding.UTF8.GetString(ms.ToArray())); + Assert.Equal(expected, Encoding.UTF8.GetString(ms.ToArray())); + } } private class HttpBufferingFeature : IHttpBufferingFeature diff --git a/test/Microsoft.AspNetCore.Http.Connections.Tests/WebSocketsTests.cs b/test/Microsoft.AspNetCore.Http.Connections.Tests/WebSocketsTests.cs index 87cc8f1606..d965636ec9 100644 --- a/test/Microsoft.AspNetCore.Http.Connections.Tests/WebSocketsTests.cs +++ b/test/Microsoft.AspNetCore.Http.Connections.Tests/WebSocketsTests.cs @@ -38,11 +38,11 @@ namespace Microsoft.AspNetCore.Http.Connections.Tests using (StartVerifiableLog(out var loggerFactory, LogLevel.Debug)) { var pair = DuplexPipe.CreateConnectionPair(PipeOptions.Default, PipeOptions.Default); - var connection = new HttpConnectionContext("foo", pair.Transport, pair.Application); + var connection = new HttpConnectionContext("foo", pair.Transport, pair.Application, loggerFactory.CreateLogger("HttpConnectionContext1")); using (var feature = new TestWebSocketConnectionFeature()) { - var connectionContext = new HttpConnectionContext(string.Empty, null, null); + var connectionContext = new HttpConnectionContext(string.Empty, null, null, loggerFactory.CreateLogger("HttpConnectionContext2")); var ws = new WebSocketsTransport(new WebSocketOptions(), connection.Application, connectionContext, loggerFactory); // Give the server socket to the transport and run it @@ -86,11 +86,11 @@ namespace Microsoft.AspNetCore.Http.Connections.Tests using (StartVerifiableLog(out var loggerFactory, LogLevel.Debug)) { var pair = DuplexPipe.CreateConnectionPair(PipeOptions.Default, PipeOptions.Default); - var connection = new HttpConnectionContext("foo", pair.Transport, pair.Application); + var connection = new HttpConnectionContext("foo", pair.Transport, pair.Application, loggerFactory.CreateLogger("HttpConnectionContext1")); using (var feature = new TestWebSocketConnectionFeature()) { - var connectionContext = new HttpConnectionContext(string.Empty, null, null); + var connectionContext = new HttpConnectionContext(string.Empty, null, null, loggerFactory.CreateLogger("HttpConnectionContext2")); connectionContext.ActiveFormat = transferFormat; var ws = new WebSocketsTransport(new WebSocketOptions(), connection.Application, connectionContext, loggerFactory); @@ -123,7 +123,7 @@ namespace Microsoft.AspNetCore.Http.Connections.Tests using (StartVerifiableLog(out var loggerFactory, LogLevel.Debug)) { var pair = DuplexPipe.CreateConnectionPair(PipeOptions.Default, PipeOptions.Default); - var connection = new HttpConnectionContext("foo", pair.Transport, pair.Application); + var connection = new HttpConnectionContext("foo", pair.Transport, pair.Application, loggerFactory.CreateLogger("HttpConnectionContext1")); using (var feature = new TestWebSocketConnectionFeature()) { @@ -146,7 +146,7 @@ namespace Microsoft.AspNetCore.Http.Connections.Tests } } - var connectionContext = new HttpConnectionContext(string.Empty, null, null); + var connectionContext = new HttpConnectionContext(string.Empty, null, null, loggerFactory.CreateLogger("HttpConnectionContext2")); var ws = new WebSocketsTransport(new WebSocketOptions(), connection.Application, connectionContext, loggerFactory); // Give the server socket to the transport and run it