diff --git a/test/Microsoft.AspNetCore.WebSockets.Test/IWebHostPortExtensions.cs b/test/Microsoft.AspNetCore.WebSockets.Test/IWebHostPortExtensions.cs new file mode 100644 index 0000000000..d3b53681f4 --- /dev/null +++ b/test/Microsoft.AspNetCore.WebSockets.Test/IWebHostPortExtensions.cs @@ -0,0 +1,30 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Collections.Generic; +using System.Linq; +using Microsoft.AspNetCore.Hosting.Server.Features; + +namespace Microsoft.AspNetCore.Hosting +{ + public static class IWebHostPortExtensions + { + public static int GetPort(this IWebHost host) + { + return host.GetPorts().First(); + } + + public static IEnumerable GetPorts(this IWebHost host) + { + return host.GetUris() + .Select(u => u.Port); + } + + public static IEnumerable GetUris(this IWebHost host) + { + return host.ServerFeatures.Get().Addresses + .Select(a => new Uri(a)); + } + } +} \ No newline at end of file diff --git a/test/Microsoft.AspNetCore.WebSockets.Test/KestrelWebSocketHelpers.cs b/test/Microsoft.AspNetCore.WebSockets.Test/KestrelWebSocketHelpers.cs index b41200f8b1..8f24cb92e7 100644 --- a/test/Microsoft.AspNetCore.WebSockets.Test/KestrelWebSocketHelpers.cs +++ b/test/Microsoft.AspNetCore.WebSockets.Test/KestrelWebSocketHelpers.cs @@ -14,7 +14,7 @@ namespace Microsoft.AspNetCore.WebSockets.Test { public class KestrelWebSocketHelpers { - public static IDisposable CreateServer(ILoggerFactory loggerFactory, Func app, int clientPort, Action configure = null) + public static IDisposable CreateServer(ILoggerFactory loggerFactory, out int port, Func app, Action configure = null) { configure = configure ?? (o => { }); Action startup = builder => @@ -46,7 +46,7 @@ namespace Microsoft.AspNetCore.WebSockets.Test var configBuilder = new ConfigurationBuilder(); configBuilder.AddInMemoryCollection(); var config = configBuilder.Build(); - config["server.urls"] = $"http://localhost:{clientPort}"; + config["server.urls"] = $"http://127.0.0.1:0"; var host = new WebHostBuilder() .ConfigureServices(s => @@ -60,6 +60,7 @@ namespace Microsoft.AspNetCore.WebSockets.Test .Build(); host.Start(); + port = host.GetPort(); return host; } diff --git a/test/Microsoft.AspNetCore.WebSockets.Test/Microsoft.AspNetCore.WebSockets.Test.csproj b/test/Microsoft.AspNetCore.WebSockets.Test/Microsoft.AspNetCore.WebSockets.Test.csproj index c906aa0f91..5e7f2eb67e 100644 --- a/test/Microsoft.AspNetCore.WebSockets.Test/Microsoft.AspNetCore.WebSockets.Test.csproj +++ b/test/Microsoft.AspNetCore.WebSockets.Test/Microsoft.AspNetCore.WebSockets.Test.csproj @@ -10,7 +10,6 @@ - diff --git a/test/Microsoft.AspNetCore.WebSockets.Test/WebSocketMiddlewareTests.cs b/test/Microsoft.AspNetCore.WebSockets.Test/WebSocketMiddlewareTests.cs index 1d179b34e2..116877df61 100644 --- a/test/Microsoft.AspNetCore.WebSockets.Test/WebSocketMiddlewareTests.cs +++ b/test/Microsoft.AspNetCore.WebSockets.Test/WebSocketMiddlewareTests.cs @@ -8,7 +8,6 @@ using System.Net.WebSockets; using System.Text; using System.Threading; using System.Threading.Tasks; -using Microsoft.AspNetCore.Server.IntegrationTesting.Common; using Microsoft.AspNetCore.Testing.xunit; using Microsoft.AspNetCore.WebSockets.Internal; using Microsoft.Extensions.Logging.Testing; @@ -26,28 +25,18 @@ namespace Microsoft.AspNetCore.WebSockets.Test #endif public class WebSocketMiddlewareTests : LoggedTest { - private readonly int ClientPort; - private readonly string ClientAddress; - - public WebSocketMiddlewareTests() - { - ClientPort = TestPortHelper.GetNextPort(); - ClientAddress = $"ws://localhost:{ClientPort}/"; - } - [ConditionalFact] public async Task Connect_Success() { - using (var server = KestrelWebSocketHelpers.CreateServer(LoggerFactory, async context => + using (var server = KestrelWebSocketHelpers.CreateServer(LoggerFactory, out var port, async context => { Assert.True(context.WebSockets.IsWebSocketRequest); var webSocket = await context.WebSockets.AcceptWebSocketAsync(); - }, - ClientPort)) + })) { using (var client = new ClientWebSocket()) { - await client.ConnectAsync(new Uri(ClientAddress), CancellationToken.None); + await client.ConnectAsync(new Uri($"ws://localhost:{port}/"), CancellationToken.None); } } } @@ -55,20 +44,19 @@ namespace Microsoft.AspNetCore.WebSockets.Test [ConditionalFact] public async Task NegotiateSubProtocol_Success() { - using (var server = KestrelWebSocketHelpers.CreateServer(LoggerFactory, async context => + using (var server = KestrelWebSocketHelpers.CreateServer(LoggerFactory, out var port, async context => { Assert.True(context.WebSockets.IsWebSocketRequest); Assert.Equal("alpha, bravo, charlie", context.Request.Headers["Sec-WebSocket-Protocol"]); var webSocket = await context.WebSockets.AcceptWebSocketAsync("Bravo"); - }, - ClientPort)) + })) { using (var client = new ClientWebSocket()) { client.Options.AddSubProtocol("alpha"); client.Options.AddSubProtocol("bravo"); client.Options.AddSubProtocol("charlie"); - await client.ConnectAsync(new Uri(ClientAddress), CancellationToken.None); + await client.ConnectAsync(new Uri($"ws://localhost:{port}/"), CancellationToken.None); // The Windows version of ClientWebSocket uses the casing from the header (Bravo) // However, the Managed version seems match the header against the list generated by @@ -84,7 +72,7 @@ namespace Microsoft.AspNetCore.WebSockets.Test [ConditionalFact] public async Task SendEmptyData_Success() { - using (var server = KestrelWebSocketHelpers.CreateServer(LoggerFactory, async context => + using (var server = KestrelWebSocketHelpers.CreateServer(LoggerFactory, out var port, async context => { Assert.True(context.WebSockets.IsWebSocketRequest); var webSocket = await context.WebSockets.AcceptWebSocketAsync(); @@ -94,12 +82,11 @@ namespace Microsoft.AspNetCore.WebSockets.Test Assert.True(result.EndOfMessage); Assert.Equal(0, result.Count); Assert.Equal(WebSocketMessageType.Binary, result.MessageType); - }, - ClientPort)) + })) { using (var client = new ClientWebSocket()) { - await client.ConnectAsync(new Uri(ClientAddress), CancellationToken.None); + await client.ConnectAsync(new Uri($"ws://localhost:{port}/"), CancellationToken.None); var orriginalData = new byte[0]; await client.SendAsync(new ArraySegment(orriginalData), WebSocketMessageType.Binary, true, CancellationToken.None); } @@ -110,7 +97,7 @@ namespace Microsoft.AspNetCore.WebSockets.Test public async Task SendShortData_Success() { var orriginalData = Encoding.UTF8.GetBytes("Hello World"); - using (var server = KestrelWebSocketHelpers.CreateServer(LoggerFactory, async context => + using (var server = KestrelWebSocketHelpers.CreateServer(LoggerFactory, out var port, async context => { Assert.True(context.WebSockets.IsWebSocketRequest); var webSocket = await context.WebSockets.AcceptWebSocketAsync(); @@ -121,12 +108,11 @@ namespace Microsoft.AspNetCore.WebSockets.Test Assert.Equal(orriginalData.Length, result.Count); Assert.Equal(WebSocketMessageType.Binary, result.MessageType); Assert.Equal(orriginalData, serverBuffer); - }, - ClientPort)) + })) { using (var client = new ClientWebSocket()) { - await client.ConnectAsync(new Uri(ClientAddress), CancellationToken.None); + await client.ConnectAsync(new Uri($"ws://localhost:{port}/"), CancellationToken.None); await client.SendAsync(new ArraySegment(orriginalData), WebSocketMessageType.Binary, true, CancellationToken.None); } } @@ -136,7 +122,7 @@ namespace Microsoft.AspNetCore.WebSockets.Test public async Task SendMediumData_Success() { var orriginalData = Encoding.UTF8.GetBytes(new string('a', 130)); - using (var server = KestrelWebSocketHelpers.CreateServer(LoggerFactory, async context => + using (var server = KestrelWebSocketHelpers.CreateServer(LoggerFactory, out var port, async context => { Assert.True(context.WebSockets.IsWebSocketRequest); var webSocket = await context.WebSockets.AcceptWebSocketAsync(); @@ -147,12 +133,11 @@ namespace Microsoft.AspNetCore.WebSockets.Test Assert.Equal(orriginalData.Length, result.Count); Assert.Equal(WebSocketMessageType.Binary, result.MessageType); Assert.Equal(orriginalData, serverBuffer); - }, - ClientPort)) + })) { using (var client = new ClientWebSocket()) { - await client.ConnectAsync(new Uri(ClientAddress), CancellationToken.None); + await client.ConnectAsync(new Uri($"ws://localhost:{port}/"), CancellationToken.None); await client.SendAsync(new ArraySegment(orriginalData), WebSocketMessageType.Binary, true, CancellationToken.None); } } @@ -162,7 +147,7 @@ namespace Microsoft.AspNetCore.WebSockets.Test public async Task SendLongData_Success() { var orriginalData = Encoding.UTF8.GetBytes(new string('a', 0x1FFFF)); - using (var server = KestrelWebSocketHelpers.CreateServer(LoggerFactory, async context => + using (var server = KestrelWebSocketHelpers.CreateServer(LoggerFactory, out var port, async context => { Assert.True(context.WebSockets.IsWebSocketRequest); var webSocket = await context.WebSockets.AcceptWebSocketAsync(); @@ -185,12 +170,11 @@ namespace Microsoft.AspNetCore.WebSockets.Test Assert.Equal(WebSocketMessageType.Text, result.MessageType); Assert.Equal(orriginalData, serverBuffer); - }, - ClientPort)) + })) { using (var client = new ClientWebSocket()) { - await client.ConnectAsync(new Uri(ClientAddress), CancellationToken.None); + await client.ConnectAsync(new Uri($"ws://localhost:{port}/"), CancellationToken.None); await client.SendAsync(new ArraySegment(orriginalData), WebSocketMessageType.Binary, true, CancellationToken.None); } } @@ -200,7 +184,7 @@ namespace Microsoft.AspNetCore.WebSockets.Test public async Task SendFragmentedData_Success() { var orriginalData = Encoding.UTF8.GetBytes("Hello World"); - using (var server = KestrelWebSocketHelpers.CreateServer(LoggerFactory, async context => + using (var server = KestrelWebSocketHelpers.CreateServer(LoggerFactory, out var port, async context => { Assert.True(context.WebSockets.IsWebSocketRequest); var webSocket = await context.WebSockets.AcceptWebSocketAsync(); @@ -227,12 +211,11 @@ namespace Microsoft.AspNetCore.WebSockets.Test Assert.Equal(WebSocketMessageType.Binary, result.MessageType); Assert.Equal(orriginalData, serverBuffer); - }, - ClientPort)) + })) { using (var client = new ClientWebSocket()) { - await client.ConnectAsync(new Uri(ClientAddress), CancellationToken.None); + await client.ConnectAsync(new Uri($"ws://localhost:{port}/"), CancellationToken.None); await client.SendAsync(new ArraySegment(orriginalData, 0, 2), WebSocketMessageType.Binary, false, CancellationToken.None); await client.SendAsync(new ArraySegment(orriginalData, 2, 2), WebSocketMessageType.Binary, false, CancellationToken.None); await client.SendAsync(new ArraySegment(orriginalData, 4, 7), WebSocketMessageType.Binary, true, CancellationToken.None); @@ -244,18 +227,17 @@ namespace Microsoft.AspNetCore.WebSockets.Test public async Task ReceiveShortData_Success() { var orriginalData = Encoding.UTF8.GetBytes("Hello World"); - using (var server = KestrelWebSocketHelpers.CreateServer(LoggerFactory, async context => + using (var server = KestrelWebSocketHelpers.CreateServer(LoggerFactory, out var port, async context => { Assert.True(context.WebSockets.IsWebSocketRequest); var webSocket = await context.WebSockets.AcceptWebSocketAsync(); await webSocket.SendAsync(new ArraySegment(orriginalData), WebSocketMessageType.Binary, true, CancellationToken.None); - }, - ClientPort)) + })) { using (var client = new ClientWebSocket()) { - await client.ConnectAsync(new Uri(ClientAddress), CancellationToken.None); + await client.ConnectAsync(new Uri($"ws://localhost:{port}/"), CancellationToken.None); var clientBuffer = new byte[orriginalData.Length]; var result = await client.ReceiveAsync(new ArraySegment(clientBuffer), CancellationToken.None); Assert.True(result.EndOfMessage); @@ -270,18 +252,17 @@ namespace Microsoft.AspNetCore.WebSockets.Test public async Task ReceiveMediumData_Success() { var orriginalData = Encoding.UTF8.GetBytes(new string('a', 130)); - using (var server = KestrelWebSocketHelpers.CreateServer(LoggerFactory, async context => + using (var server = KestrelWebSocketHelpers.CreateServer(LoggerFactory, out var port, async context => { Assert.True(context.WebSockets.IsWebSocketRequest); var webSocket = await context.WebSockets.AcceptWebSocketAsync(); await webSocket.SendAsync(new ArraySegment(orriginalData), WebSocketMessageType.Binary, true, CancellationToken.None); - }, - ClientPort)) + })) { using (var client = new ClientWebSocket()) { - await client.ConnectAsync(new Uri(ClientAddress), CancellationToken.None); + await client.ConnectAsync(new Uri($"ws://localhost:{port}/"), CancellationToken.None); var clientBuffer = new byte[orriginalData.Length]; var result = await client.ReceiveAsync(new ArraySegment(clientBuffer), CancellationToken.None); Assert.True(result.EndOfMessage); @@ -296,18 +277,17 @@ namespace Microsoft.AspNetCore.WebSockets.Test public async Task ReceiveLongData() { var orriginalData = Encoding.UTF8.GetBytes(new string('a', 0x1FFFF)); - using (var server = KestrelWebSocketHelpers.CreateServer(LoggerFactory, async context => + using (var server = KestrelWebSocketHelpers.CreateServer(LoggerFactory, out var port, async context => { Assert.True(context.WebSockets.IsWebSocketRequest); var webSocket = await context.WebSockets.AcceptWebSocketAsync(); await webSocket.SendAsync(new ArraySegment(orriginalData), WebSocketMessageType.Binary, true, CancellationToken.None); - }, - ClientPort)) + })) { using (var client = new ClientWebSocket()) { - await client.ConnectAsync(new Uri(ClientAddress), CancellationToken.None); + await client.ConnectAsync(new Uri($"ws://localhost:{port}/"), CancellationToken.None); var clientBuffer = new byte[orriginalData.Length]; WebSocketReceiveResult result; int receivedCount = 0; @@ -330,7 +310,7 @@ namespace Microsoft.AspNetCore.WebSockets.Test public async Task ReceiveFragmentedData_Success() { var orriginalData = Encoding.UTF8.GetBytes("Hello World"); - using (var server = KestrelWebSocketHelpers.CreateServer(LoggerFactory, async context => + using (var server = KestrelWebSocketHelpers.CreateServer(LoggerFactory, out var port, async context => { Assert.True(context.WebSockets.IsWebSocketRequest); var webSocket = await context.WebSockets.AcceptWebSocketAsync(); @@ -338,12 +318,11 @@ namespace Microsoft.AspNetCore.WebSockets.Test await webSocket.SendAsync(new ArraySegment(orriginalData, 0, 2), WebSocketMessageType.Binary, false, CancellationToken.None); await webSocket.SendAsync(new ArraySegment(orriginalData, 2, 2), WebSocketMessageType.Binary, false, CancellationToken.None); await webSocket.SendAsync(new ArraySegment(orriginalData, 4, 7), WebSocketMessageType.Binary, true, CancellationToken.None); - }, - ClientPort)) + })) { using (var client = new ClientWebSocket()) { - await client.ConnectAsync(new Uri(ClientAddress), CancellationToken.None); + await client.ConnectAsync(new Uri($"ws://localhost:{port}/"), CancellationToken.None); var clientBuffer = new byte[orriginalData.Length]; var result = await client.ReceiveAsync(new ArraySegment(clientBuffer), CancellationToken.None); Assert.False(result.EndOfMessage); @@ -374,7 +353,7 @@ namespace Microsoft.AspNetCore.WebSockets.Test public async Task SendClose_Success() { string closeDescription = "Test Closed"; - using (var server = KestrelWebSocketHelpers.CreateServer(LoggerFactory, async context => + using (var server = KestrelWebSocketHelpers.CreateServer(LoggerFactory, out var port, async context => { Assert.True(context.WebSockets.IsWebSocketRequest); var webSocket = await context.WebSockets.AcceptWebSocketAsync(); @@ -386,12 +365,11 @@ namespace Microsoft.AspNetCore.WebSockets.Test Assert.Equal(WebSocketMessageType.Close, result.MessageType); Assert.Equal(WebSocketCloseStatus.NormalClosure, result.CloseStatus); Assert.Equal(closeDescription, result.CloseStatusDescription); - }, - ClientPort)) + })) { using (var client = new ClientWebSocket()) { - await client.ConnectAsync(new Uri(ClientAddress), CancellationToken.None); + await client.ConnectAsync(new Uri($"ws://localhost:{port}/"), CancellationToken.None); await client.CloseOutputAsync(WebSocketCloseStatus.NormalClosure, closeDescription, CancellationToken.None); Assert.Equal(WebSocketState.CloseSent, client.State); @@ -403,18 +381,17 @@ namespace Microsoft.AspNetCore.WebSockets.Test public async Task ReceiveClose_Success() { string closeDescription = "Test Closed"; - using (var server = KestrelWebSocketHelpers.CreateServer(LoggerFactory, async context => + using (var server = KestrelWebSocketHelpers.CreateServer(LoggerFactory, out var port, async context => { Assert.True(context.WebSockets.IsWebSocketRequest); var webSocket = await context.WebSockets.AcceptWebSocketAsync(); await webSocket.CloseOutputAsync(WebSocketCloseStatus.NormalClosure, closeDescription, CancellationToken.None); - }, - ClientPort)) + })) { using (var client = new ClientWebSocket()) { - await client.ConnectAsync(new Uri(ClientAddress), CancellationToken.None); + await client.ConnectAsync(new Uri($"ws://localhost:{port}/"), CancellationToken.None); var clientBuffer = new byte[1024]; var result = await client.ReceiveAsync(new ArraySegment(clientBuffer), CancellationToken.None); Assert.True(result.EndOfMessage); @@ -432,7 +409,7 @@ namespace Microsoft.AspNetCore.WebSockets.Test public async Task CloseFromOpen_Success() { string closeDescription = "Test Closed"; - using (var server = KestrelWebSocketHelpers.CreateServer(LoggerFactory, async context => + using (var server = KestrelWebSocketHelpers.CreateServer(LoggerFactory, out var port, async context => { Assert.True(context.WebSockets.IsWebSocketRequest); var webSocket = await context.WebSockets.AcceptWebSocketAsync(); @@ -446,12 +423,11 @@ namespace Microsoft.AspNetCore.WebSockets.Test Assert.Equal(closeDescription, result.CloseStatusDescription); await webSocket.CloseAsync(result.CloseStatus.Value, result.CloseStatusDescription, CancellationToken.None); - }, - ClientPort)) + })) { using (var client = new ClientWebSocket()) { - await client.ConnectAsync(new Uri(ClientAddress), CancellationToken.None); + await client.ConnectAsync(new Uri($"ws://localhost:{port}/"), CancellationToken.None); await client.CloseAsync(WebSocketCloseStatus.NormalClosure, closeDescription, CancellationToken.None); Assert.Equal(WebSocketState.Closed, client.State); @@ -463,7 +439,7 @@ namespace Microsoft.AspNetCore.WebSockets.Test public async Task CloseFromCloseSent_Success() { string closeDescription = "Test Closed"; - using (var server = KestrelWebSocketHelpers.CreateServer(LoggerFactory, async context => + using (var server = KestrelWebSocketHelpers.CreateServer(LoggerFactory, out var port, async context => { Assert.True(context.WebSockets.IsWebSocketRequest); var webSocket = await context.WebSockets.AcceptWebSocketAsync(); @@ -477,12 +453,11 @@ namespace Microsoft.AspNetCore.WebSockets.Test Assert.Equal(closeDescription, result.CloseStatusDescription); await webSocket.CloseAsync(result.CloseStatus.Value, result.CloseStatusDescription, CancellationToken.None); - }, - ClientPort)) + })) { using (var client = new ClientWebSocket()) { - await client.ConnectAsync(new Uri(ClientAddress), CancellationToken.None); + await client.ConnectAsync(new Uri($"ws://localhost:{port}/"), CancellationToken.None); await client.CloseOutputAsync(WebSocketCloseStatus.NormalClosure, closeDescription, CancellationToken.None); Assert.Equal(WebSocketState.CloseSent, client.State); @@ -496,7 +471,7 @@ namespace Microsoft.AspNetCore.WebSockets.Test public async Task CloseFromCloseReceived_Success() { string closeDescription = "Test Closed"; - using (var server = KestrelWebSocketHelpers.CreateServer(LoggerFactory, async context => + using (var server = KestrelWebSocketHelpers.CreateServer(LoggerFactory, out var port, async context => { Assert.True(context.WebSockets.IsWebSocketRequest); var webSocket = await context.WebSockets.AcceptWebSocketAsync(); @@ -510,12 +485,11 @@ namespace Microsoft.AspNetCore.WebSockets.Test Assert.Equal(WebSocketMessageType.Close, result.MessageType); Assert.Equal(WebSocketCloseStatus.NormalClosure, result.CloseStatus); Assert.Equal(closeDescription, result.CloseStatusDescription); - }, - ClientPort)) + })) { using (var client = new ClientWebSocket()) { - await client.ConnectAsync(new Uri(ClientAddress), CancellationToken.None); + await client.ConnectAsync(new Uri($"ws://localhost:{port}/"), CancellationToken.None); var clientBuffer = new byte[1024]; var result = await client.ReceiveAsync(new ArraySegment(clientBuffer), CancellationToken.None); Assert.True(result.EndOfMessage); @@ -543,12 +517,11 @@ namespace Microsoft.AspNetCore.WebSockets.Test [InlineData(HttpStatusCode.OK, "http://ExAmPLE.cOm")] public async Task OriginIsValidatedForWebSocketRequests(HttpStatusCode expectedCode, params string[] origins) { - using (var server = KestrelWebSocketHelpers.CreateServer(LoggerFactory, context => + using (var server = KestrelWebSocketHelpers.CreateServer(LoggerFactory, out var port, context => { Assert.True(context.WebSockets.IsWebSocketRequest); return Task.CompletedTask; }, - ClientPort, o => { if (origins != null) @@ -562,7 +535,7 @@ namespace Microsoft.AspNetCore.WebSockets.Test { using (var client = new HttpClient()) { - var uri = new UriBuilder(ClientAddress); + var uri = new UriBuilder(new Uri($"ws://localhost:{port}/")); uri.Scheme = "http"; // Craft a valid WebSocket Upgrade request @@ -587,17 +560,16 @@ namespace Microsoft.AspNetCore.WebSockets.Test [Fact] public async Task OriginIsNotValidatedForNonWebSocketRequests() { - using (var server = KestrelWebSocketHelpers.CreateServer(LoggerFactory, context => + using (var server = KestrelWebSocketHelpers.CreateServer(LoggerFactory, out var port, context => { Assert.False(context.WebSockets.IsWebSocketRequest); return Task.CompletedTask; }, - ClientPort, o => o.AllowedOrigins.Add("http://example.com"))) { using (var client = new HttpClient()) { - var uri = new UriBuilder(ClientAddress); + var uri = new UriBuilder(new Uri($"ws://localhost:{port}/")); uri.Scheme = "http"; using (var request = new HttpRequestMessage(HttpMethod.Get, uri.ToString()))