diff --git a/test/Common/ServerFixture.cs b/test/Common/ServerFixture.cs index 2b882f0f3f..115f57bd44 100644 --- a/test/Common/ServerFixture.cs +++ b/test/Common/ServerFixture.cs @@ -3,6 +3,8 @@ using System; using System.IO; +using System.Net; +using System.Net.Sockets; using System.Threading.Tasks; using Microsoft.AspNetCore.Hosting; using Microsoft.Extensions.DependencyInjection; @@ -21,7 +23,7 @@ namespace Microsoft.AspNetCore.SignalR.Tests.Common private IApplicationLifetime _lifetime; private readonly IDisposable _logToken; - public string BaseUrl => "http://localhost:3000"; + public string BaseUrl { get; private set; } public string WebSocketsUrl => BaseUrl.Replace("http", "ws"); @@ -30,6 +32,7 @@ namespace Microsoft.AspNetCore.SignalR.Tests.Common var testLog = AssemblyTestLog.ForAssembly(typeof(ServerFixture).Assembly); _logToken = testLog.StartTestLog(null, $"{nameof(ServerFixture)}_{typeof(TStartup).Name}" , out _loggerFactory, "ServerFixture"); _logger = _loggerFactory.CreateLogger>(); + BaseUrl = "http://localhost:" + GetNextPort(); StartServer(); } @@ -90,5 +93,20 @@ namespace Microsoft.AspNetCore.SignalR.Tests.Common return _loggerFactory.CreateLogger(categoryName); } } + + // Copied from https://github.com/aspnet/KestrelHttpServer/blob/47f1db20e063c2da75d9d89653fad4eafe24446c/test/Microsoft.AspNetCore.Server.Kestrel.FunctionalTests/AddressRegistrationTests.cs#L508 + private static int GetNextPort() + { + using (var socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp)) + { + // Let the OS assign the next available port. Unless we cycle through all ports + // on a test run, the OS will always increment the port number when making these calls. + // This prevents races in parallel test runs where a test is already bound to + // a given port, and a new test is able to bind to the same port due to port + // reuse being enabled by default by the OS. + socket.Bind(new IPEndPoint(IPAddress.Loopback, 0)); + return ((IPEndPoint)socket.LocalEndPoint).Port; + } + } } }