Merge pull request #3243 from dotnet-maestro-bot/merge/release/2.2-to-master

[automated] Merge branch 'release/2.2' => 'master'
This commit is contained in:
BrennanConroy 2018-10-31 16:28:19 -07:00 committed by GitHub
commit e5e51ac6ca
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 389 additions and 302 deletions

View File

@ -7,17 +7,26 @@ 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();
using (StartVerifiableLog(out var loggerFactory))
{
var connectionManager = CreateConnectionManager(loggerFactory);
var connection = connectionManager.CreateConnection();
Assert.NotNull(connection.ConnectionId);
@ -29,6 +38,7 @@ namespace Microsoft.AspNetCore.Http.Connections.Tests
Assert.NotNull(connection.Transport);
Assert.NotNull(connection.Application);
}
}
[Theory]
[InlineData(ConnectionStates.ClosedUngracefully | ConnectionStates.ApplicationNotFaulted | ConnectionStates.TransportNotFaulted)]
@ -41,12 +51,14 @@ namespace Microsoft.AspNetCore.Http.Connections.Tests
[InlineData(ConnectionStates.CloseGracefully | ConnectionStates.ApplicationFaulted | ConnectionStates.TransportFaulted)]
[InlineData(ConnectionStates.CloseGracefully | ConnectionStates.ApplicationFaulted | ConnectionStates.TransportNotFaulted)]
public async Task DisposingConnectionsClosesBothSidesOfThePipe(ConnectionStates states)
{
using (StartVerifiableLog(out var loggerFactory))
{
var closeGracefully = (states & ConnectionStates.CloseGracefully) != 0;
var applicationFaulted = (states & ConnectionStates.ApplicationFaulted) != 0;
var transportFaulted = (states & ConnectionStates.TransportFaulted) != 0;
var connectionManager = CreateConnectionManager();
var connectionManager = CreateConnectionManager(loggerFactory);
var connection = connectionManager.CreateConnection();
if (applicationFaulted)
@ -106,11 +118,14 @@ namespace Microsoft.AspNetCore.Http.Connections.Tests
await Task.WhenAll(applicationInputTcs.Task, applicationOutputTcs.Task, transportInputTcs.Task, transportOutputTcs.Task).OrTimeout();
}
}
[Fact]
public void NewConnectionsCanBeRetrieved()
{
var connectionManager = CreateConnectionManager();
using (StartVerifiableLog(out var loggerFactory))
{
var connectionManager = CreateConnectionManager(loggerFactory);
var connection = connectionManager.CreateConnection();
Assert.NotNull(connection.ConnectionId);
@ -118,11 +133,14 @@ namespace Microsoft.AspNetCore.Http.Connections.Tests
Assert.True(connectionManager.TryGetConnection(connection.ConnectionId, out var newConnection));
Assert.Same(newConnection, connection);
}
}
[Fact]
public void AddNewConnection()
{
var connectionManager = CreateConnectionManager();
using (StartVerifiableLog(out var loggerFactory))
{
var connectionManager = CreateConnectionManager(loggerFactory);
var connection = connectionManager.CreateConnection(PipeOptions.Default, PipeOptions.Default);
var transport = connection.Transport;
@ -134,11 +152,14 @@ namespace Microsoft.AspNetCore.Http.Connections.Tests
Assert.Same(newConnection, connection);
Assert.Same(transport, newConnection.Transport);
}
}
[Fact]
public void RemoveConnection()
{
var connectionManager = CreateConnectionManager();
using (StartVerifiableLog(out var loggerFactory))
{
var connectionManager = CreateConnectionManager(loggerFactory);
var connection = connectionManager.CreateConnection(PipeOptions.Default, PipeOptions.Default);
var transport = connection.Transport;
@ -153,11 +174,14 @@ namespace Microsoft.AspNetCore.Http.Connections.Tests
connectionManager.RemoveConnection(connection.ConnectionId);
Assert.False(connectionManager.TryGetConnection(connection.ConnectionId, out newConnection));
}
}
[Fact]
public async Task CloseConnectionsEndsAllPendingConnections()
{
var connectionManager = CreateConnectionManager();
using (StartVerifiableLog(out var loggerFactory))
{
var connectionManager = CreateConnectionManager(loggerFactory);
var connection = connectionManager.CreateConnection(PipeOptions.Default, PipeOptions.Default);
connection.ApplicationTask = Task.Run(async () =>
@ -198,11 +222,14 @@ namespace Microsoft.AspNetCore.Http.Connections.Tests
await connection.DisposeAsync();
}
}
[Fact]
public async Task DisposingConnectionMultipleTimesWaitsOnConnectionClose()
{
var connectionManager = CreateConnectionManager();
using (StartVerifiableLog(out var loggerFactory))
{
var connectionManager = CreateConnectionManager(loggerFactory);
var connection = connectionManager.CreateConnection(PipeOptions.Default, PipeOptions.Default);
var tcs = new TaskCompletionSource<object>(TaskCreationOptions.RunContinuationsAsynchronously);
@ -218,11 +245,14 @@ namespace Microsoft.AspNetCore.Http.Connections.Tests
await Task.WhenAll(firstTask, secondTask).OrTimeout();
}
}
[Fact]
public async Task DisposingConnectionMultipleGetsExceptionFromTransportOrApp()
{
var connectionManager = CreateConnectionManager();
using (StartVerifiableLog(out var loggerFactory))
{
var connectionManager = CreateConnectionManager(loggerFactory);
var connection = connectionManager.CreateConnection(PipeOptions.Default, PipeOptions.Default);
var tcs = new TaskCompletionSource<object>(TaskCreationOptions.RunContinuationsAsynchronously);
@ -242,11 +272,14 @@ namespace Microsoft.AspNetCore.Http.Connections.Tests
exception = await Assert.ThrowsAsync<InvalidOperationException>(async () => await secondTask.OrTimeout());
Assert.Equal("Error", exception.Message);
}
}
[Fact]
public async Task DisposingConnectionMultipleGetsCancellation()
{
var connectionManager = CreateConnectionManager();
using (StartVerifiableLog(out var loggerFactory))
{
var connectionManager = CreateConnectionManager(loggerFactory);
var connection = connectionManager.CreateConnection(PipeOptions.Default, PipeOptions.Default);
var tcs = new TaskCompletionSource<object>(TaskCreationOptions.RunContinuationsAsynchronously);
@ -263,11 +296,14 @@ namespace Microsoft.AspNetCore.Http.Connections.Tests
await Assert.ThrowsAsync<TaskCanceledException>(async () => await firstTask.OrTimeout());
await Assert.ThrowsAsync<TaskCanceledException>(async () => await secondTask.OrTimeout());
}
}
[Fact]
public async Task DisposeInactiveConnection()
{
var connectionManager = CreateConnectionManager();
using (StartVerifiableLog(out var loggerFactory))
{
var connectionManager = CreateConnectionManager(loggerFactory);
var connection = connectionManager.CreateConnection(PipeOptions.Default, PipeOptions.Default);
Assert.NotNull(connection.ConnectionId);
@ -276,11 +312,14 @@ namespace Microsoft.AspNetCore.Http.Connections.Tests
await connection.DisposeAsync();
Assert.Equal(HttpConnectionStatus.Disposed, connection.Status);
}
}
[Fact]
public async Task DisposeInactiveConnectionWithNoPipes()
{
var connectionManager = CreateConnectionManager();
using (StartVerifiableLog(out var loggerFactory))
{
var connectionManager = CreateConnectionManager(loggerFactory);
var connection = connectionManager.CreateConnection();
Assert.NotNull(connection.ConnectionId);
@ -290,12 +329,15 @@ namespace Microsoft.AspNetCore.Http.Connections.Tests
await connection.DisposeAsync();
Assert.Equal(HttpConnectionStatus.Disposed, connection.Status);
}
}
[Fact]
public async Task ApplicationLifetimeIsHookedUp()
{
using (StartVerifiableLog(out var loggerFactory))
{
var appLifetime = new TestApplicationLifetime();
var connectionManager = CreateConnectionManager(appLifetime);
var connectionManager = CreateConnectionManager(loggerFactory, appLifetime);
var tcs = new TaskCompletionSource<object>();
appLifetime.Start();
@ -313,14 +355,17 @@ namespace Microsoft.AspNetCore.Http.Connections.Tests
// Connection should be disposed so this should complete immediately
await tcs.Task.OrTimeout();
}
}
[Fact]
public async Task ApplicationLifetimeCanStartBeforeHttpConnectionManagerInitialized()
{
using (StartVerifiableLog(out var loggerFactory))
{
var appLifetime = new TestApplicationLifetime();
appLifetime.Start();
var connectionManager = CreateConnectionManager(appLifetime);
var connectionManager = CreateConnectionManager(loggerFactory, appLifetime);
var tcs = new TaskCompletionSource<object>();
var connection = connectionManager.CreateConnection(PipeOptions.Default, PipeOptions.Default);
@ -336,11 +381,12 @@ namespace Microsoft.AspNetCore.Http.Connections.Tests
// 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]

View File

@ -9,22 +9,31 @@ 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()
{
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 poll = new LongPollingTransport(CancellationToken.None, connection.Application.Input, loggerFactory);
connection.Transport.Output.Complete();
@ -32,16 +41,19 @@ namespace Microsoft.AspNetCore.Http.Connections.Tests
Assert.Equal(204, context.Response.StatusCode);
}
}
[Fact]
public async Task Set200StatusCodeWhenTimeoutTokenFires()
{
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 timeoutToken = new CancellationToken(true);
var poll = new LongPollingTransport(timeoutToken, connection.Application.Input, loggerFactory: new LoggerFactory());
var poll = new LongPollingTransport(timeoutToken, connection.Application.Input, loggerFactory);
using (var cts = CancellationTokenSource.CreateLinkedTokenSource(timeoutToken, context.RequestAborted))
{
@ -51,15 +63,18 @@ namespace Microsoft.AspNetCore.Http.Connections.Tests
Assert.Equal(200, context.Response.StatusCode);
}
}
}
[Fact]
public async Task FrameSentAsSingleResponse()
{
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 poll = new LongPollingTransport(CancellationToken.None, connection.Application.Input, loggerFactory);
var ms = new MemoryStream();
context.Response.Body = ms;
@ -71,15 +86,18 @@ namespace Microsoft.AspNetCore.Http.Connections.Tests
Assert.Equal(200, context.Response.StatusCode);
Assert.Equal("Hello World", Encoding.UTF8.GetString(ms.ToArray()));
}
}
[Fact]
public async Task MultipleFramesSentAsSingleResponse()
{
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 poll = new LongPollingTransport(CancellationToken.None, connection.Application.Input, loggerFactory);
var ms = new MemoryStream();
context.Response.Body = ms;
@ -96,6 +114,7 @@ namespace Microsoft.AspNetCore.Http.Connections.Tests
var payload = ms.ToArray();
Assert.Equal("Hello World", Encoding.UTF8.GetString(payload));
}
}
[Fact]
public void CheckLongPollingTimeoutValue()

View File

@ -11,19 +11,28 @@ 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()
{
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();
@ -32,9 +41,12 @@ namespace Microsoft.AspNetCore.Http.Connections.Tests
Assert.Equal("text/event-stream", context.Response.ContentType);
Assert.Equal("no-cache", context.Response.Headers["Cache-Control"]);
}
}
[Fact]
public async Task SSETurnsResponseBufferingOff()
{
using (StartVerifiableLog(out var loggerFactory))
{
var pair = DuplexPipe.CreateConnectionPair(PipeOptions.Default, PipeOptions.Default);
var connection = new DefaultConnectionContext("foo", pair.Transport, pair.Application);
@ -42,7 +54,7 @@ namespace Microsoft.AspNetCore.Http.Connections.Tests
var feature = new HttpBufferingFeature();
context.Features.Set<IHttpBufferingFeature>(feature);
var sse = new ServerSentEventsTransport(connection.Application.Input, connectionId: connection.ConnectionId, loggerFactory: new LoggerFactory());
var sse = new ServerSentEventsTransport(connection.Application.Input, connectionId: connection.ConnectionId, loggerFactory);
connection.Transport.Output.Complete();
@ -50,9 +62,12 @@ namespace Microsoft.AspNetCore.Http.Connections.Tests
Assert.True(feature.ResponseBufferingDisabled);
}
}
[Fact]
public async Task SSEWritesMessages()
{
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);
@ -60,7 +75,7 @@ namespace Microsoft.AspNetCore.Http.Connections.Tests
var ms = new MemoryStream();
context.Response.Body = ms;
var sse = new ServerSentEventsTransport(connection.Application.Input, connectionId: string.Empty, loggerFactory: new LoggerFactory());
var sse = new ServerSentEventsTransport(connection.Application.Input, connectionId: string.Empty, loggerFactory);
var task = sse.ProcessRequestAsync(context, context.RequestAborted);
@ -69,9 +84,12 @@ namespace Microsoft.AspNetCore.Http.Connections.Tests
await task.OrTimeout();
Assert.Equal(":\r\ndata: Hello\r\n\r\n", Encoding.ASCII.GetString(ms.ToArray()));
}
}
[Fact]
public async Task SSEWritesVeryLargeMessages()
{
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);
@ -79,7 +97,7 @@ namespace Microsoft.AspNetCore.Http.Connections.Tests
var ms = new MemoryStream();
context.Response.Body = ms;
var sse = new ServerSentEventsTransport(connection.Application.Input, connectionId: string.Empty, loggerFactory: new LoggerFactory());
var sse = new ServerSentEventsTransport(connection.Application.Input, connectionId: string.Empty, loggerFactory);
var task = sse.ProcessRequestAsync(context, context.RequestAborted);
@ -91,18 +109,21 @@ namespace Microsoft.AspNetCore.Http.Connections.Tests
await task.OrTimeout();
Assert.Equal(":\r\ndata: " + hText + wText + "\r\n\r\n", Encoding.ASCII.GetString(ms.ToArray()));
}
}
[Theory]
[InlineData("Hello World", ":\r\ndata: Hello World\r\n\r\n")]
[InlineData("Hello\nWorld", ":\r\ndata: Hello\r\ndata: World\r\n\r\n")]
[InlineData("Hello\r\nWorld", ":\r\ndata: Hello\r\ndata: World\r\n\r\n")]
public async Task SSEAddsAppropriateFraming(string message, string expected)
{
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);
var ms = new MemoryStream();
context.Response.Body = ms;
@ -114,6 +135,7 @@ namespace Microsoft.AspNetCore.Http.Connections.Tests
Assert.Equal(expected, Encoding.UTF8.GetString(ms.ToArray()));
}
}
private class HttpBufferingFeature : IHttpBufferingFeature
{

View File

@ -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