From 14bbba06418234f1f6d41eb2540ca26f8598fd23 Mon Sep 17 00:00:00 2001 From: Mike Harder Date: Wed, 4 May 2016 11:27:23 -0700 Subject: [PATCH] Update addresses in IServerAddressesFeature with assigned dynamic ports (#758) - Change most tests to use dynamic ports, rather than a fixed port obtained from GetNextPort(). - Add several new cases to `AddressRegistrationTests` and `ServerAddressFacts`. - Remove project `test\Microsoft.AspNetCore.Server.Kestrel.TestCommon`. It's not longer needed, since only `AddressRegistrationTests` uses `GetNextPort()`. --- KestrelHttpServer.sln | 7 - .../Http/TcpListener.cs | 4 + .../Http/TcpListenerPrimary.cs | 4 + .../KestrelServer.cs | 7 +- .../ServerAddress.cs | 18 +- .../AddressRegistrationTests.cs | 216 ++++++++++++++++-- .../IWebHostPortExtensions.cs | 25 ++ .../PathBaseTests.cs | 5 +- .../PortManager.cs | 15 -- .../RequestTests.cs | 25 +- .../ResponseTests.cs | 15 +- .../ThreadCountTests.cs | 5 +- .../project.json | 3 +- ...AspNetCore.Server.Kestrel.TestCommon.xproj | 17 -- .../PortManager.cs | 38 --- .../project.json | 18 -- .../ConnectionTests.cs | 2 +- .../EngineTests.cs | 7 +- .../HttpsConnectionFilterTests.cs | 26 +-- .../MultipleLoopTests.cs | 4 +- .../NetworkingTests.cs | 12 +- .../ServerAddressFacts.cs | 45 ++-- .../TestServer.cs | 8 +- .../project.json | 1 - 24 files changed, 316 insertions(+), 211 deletions(-) create mode 100644 test/Microsoft.AspNetCore.Server.Kestrel.FunctionalTests/IWebHostPortExtensions.cs delete mode 100644 test/Microsoft.AspNetCore.Server.Kestrel.FunctionalTests/PortManager.cs delete mode 100644 test/Microsoft.AspNetCore.Server.Kestrel.TestCommon/Microsoft.AspNetCore.Server.Kestrel.TestCommon.xproj delete mode 100644 test/Microsoft.AspNetCore.Server.Kestrel.TestCommon/PortManager.cs delete mode 100644 test/Microsoft.AspNetCore.Server.Kestrel.TestCommon/project.json diff --git a/KestrelHttpServer.sln b/KestrelHttpServer.sln index 4a215770d9..a9155550a7 100644 --- a/KestrelHttpServer.sln +++ b/KestrelHttpServer.sln @@ -34,8 +34,6 @@ Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Microsoft.AspNetCore.Server EndProject Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Microsoft.AspNetCore.Server.Kestrel.FunctionalTests", "test\Microsoft.AspNetCore.Server.Kestrel.FunctionalTests\Microsoft.AspNetCore.Server.Kestrel.FunctionalTests.xproj", "{9559A5F1-080C-4909-B6CF-7E4B3DC55748}" EndProject -Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Microsoft.AspNetCore.Server.Kestrel.TestCommon", "test\Microsoft.AspNetCore.Server.Kestrel.TestCommon\Microsoft.AspNetCore.Server.Kestrel.TestCommon.xproj", "{A485B4F9-0392-478C-B19A-F4DE6B17F491}" -EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -74,10 +72,6 @@ Global {9559A5F1-080C-4909-B6CF-7E4B3DC55748}.Debug|Any CPU.Build.0 = Debug|Any CPU {9559A5F1-080C-4909-B6CF-7E4B3DC55748}.Release|Any CPU.ActiveCfg = Release|Any CPU {9559A5F1-080C-4909-B6CF-7E4B3DC55748}.Release|Any CPU.Build.0 = Release|Any CPU - {A485B4F9-0392-478C-B19A-F4DE6B17F491}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {A485B4F9-0392-478C-B19A-F4DE6B17F491}.Debug|Any CPU.Build.0 = Debug|Any CPU - {A485B4F9-0392-478C-B19A-F4DE6B17F491}.Release|Any CPU.ActiveCfg = Release|Any CPU - {A485B4F9-0392-478C-B19A-F4DE6B17F491}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -91,6 +85,5 @@ Global {8CBA6FE3-3CC9-4420-8AA3-123E983734C2} = {327F7880-D9AF-46BD-B45C-3B7E34A01DFD} {5F64B3C3-0C2E-431A-B820-A81BBFC863DA} = {2D5D5227-4DBD-499A-96B1-76A36B03B750} {9559A5F1-080C-4909-B6CF-7E4B3DC55748} = {D3273454-EA07-41D2-BF0B-FCC3675C2483} - {A485B4F9-0392-478C-B19A-F4DE6B17F491} = {D3273454-EA07-41D2-BF0B-FCC3675C2483} EndGlobalSection EndGlobal diff --git a/src/Microsoft.AspNetCore.Server.Kestrel/Http/TcpListener.cs b/src/Microsoft.AspNetCore.Server.Kestrel/Http/TcpListener.cs index 94c7cdecd9..cc7e3f9aff 100644 --- a/src/Microsoft.AspNetCore.Server.Kestrel/Http/TcpListener.cs +++ b/src/Microsoft.AspNetCore.Server.Kestrel/Http/TcpListener.cs @@ -25,6 +25,10 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Http socket.Init(Thread.Loop, Thread.QueueCloseHandle); socket.NoDelay(ServerOptions.NoDelay); socket.Bind(ServerAddress); + + // If requested port was "0", replace with assigned dynamic port. + ServerAddress.Port = socket.GetSockIPEndPoint().Port; + socket.Listen(Constants.ListenBacklog, (stream, status, error, state) => ConnectionCallback(stream, status, error, state), this); return socket; } diff --git a/src/Microsoft.AspNetCore.Server.Kestrel/Http/TcpListenerPrimary.cs b/src/Microsoft.AspNetCore.Server.Kestrel/Http/TcpListenerPrimary.cs index 80691b51ec..926cd014b2 100644 --- a/src/Microsoft.AspNetCore.Server.Kestrel/Http/TcpListenerPrimary.cs +++ b/src/Microsoft.AspNetCore.Server.Kestrel/Http/TcpListenerPrimary.cs @@ -27,6 +27,10 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Http socket.Init(Thread.Loop, Thread.QueueCloseHandle); socket.NoDelay(ServerOptions.NoDelay); socket.Bind(ServerAddress); + + // If requested port was "0", replace with assigned dynamic port. + ServerAddress.Port = socket.GetSockIPEndPoint().Port; + socket.Listen(Constants.ListenBacklog, (stream, status, error, state) => ConnectionCallback(stream, status, error, state), this); return socket; } diff --git a/src/Microsoft.AspNetCore.Server.Kestrel/KestrelServer.cs b/src/Microsoft.AspNetCore.Server.Kestrel/KestrelServer.cs index a1b1b01947..19068784a4 100644 --- a/src/Microsoft.AspNetCore.Server.Kestrel/KestrelServer.cs +++ b/src/Microsoft.AspNetCore.Server.Kestrel/KestrelServer.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; +using System.Linq; using System.Reflection; using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Hosting.Server; @@ -96,7 +97,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel engine.Start(threadCount); var atLeastOneListener = false; - foreach (var address in _serverAddresses.Addresses) + foreach (var address in _serverAddresses.Addresses.ToArray()) { var parsedAddress = ServerAddress.FromUrl(address); if (parsedAddress == null) @@ -108,6 +109,10 @@ namespace Microsoft.AspNetCore.Server.Kestrel atLeastOneListener = true; _disposables.Push(engine.CreateServer( parsedAddress)); + + // If requested port was "0", replace with assigned dynamic port. + _serverAddresses.Addresses.Remove(address); + _serverAddresses.Addresses.Add(parsedAddress.ToString()); } } diff --git a/src/Microsoft.AspNetCore.Server.Kestrel/ServerAddress.cs b/src/Microsoft.AspNetCore.Server.Kestrel/ServerAddress.cs index a41472bbdf..536492dfb1 100644 --- a/src/Microsoft.AspNetCore.Server.Kestrel/ServerAddress.cs +++ b/src/Microsoft.AspNetCore.Server.Kestrel/ServerAddress.cs @@ -13,7 +13,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel { public string Host { get; private set; } public string PathBase { get; private set; } - public int Port { get; private set; } + public int Port { get; internal set; } public string Scheme { get; private set; } public bool IsUnixPipe @@ -36,7 +36,21 @@ namespace Microsoft.AspNetCore.Server.Kestrel public override string ToString() { - return Scheme.ToLowerInvariant() + "://" + Host.ToLowerInvariant() + ":" + Port.ToString(CultureInfo.InvariantCulture) + PathBase.ToLowerInvariant(); + if (IsUnixPipe) + { + if (String.IsNullOrEmpty(PathBase)) + { + return Scheme.ToLowerInvariant() + "://" + Host.ToLowerInvariant(); + } + else + { + return Scheme.ToLowerInvariant() + "://" + Host.ToLowerInvariant() + ":" + PathBase.ToLowerInvariant(); + } + } + else + { + return Scheme.ToLowerInvariant() + "://" + Host.ToLowerInvariant() + ":" + Port.ToString(CultureInfo.InvariantCulture) + PathBase.ToLowerInvariant(); + } } public override int GetHashCode() diff --git a/test/Microsoft.AspNetCore.Server.Kestrel.FunctionalTests/AddressRegistrationTests.cs b/test/Microsoft.AspNetCore.Server.Kestrel.FunctionalTests/AddressRegistrationTests.cs index 2422eb527f..1f5fb0a61c 100644 --- a/test/Microsoft.AspNetCore.Server.Kestrel.FunctionalTests/AddressRegistrationTests.cs +++ b/test/Microsoft.AspNetCore.Server.Kestrel.FunctionalTests/AddressRegistrationTests.cs @@ -1,11 +1,16 @@ // 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 System.Net; using System.Net.Http; +using System.Net.Sockets; using System.Threading.Tasks; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; +using Microsoft.AspNetCore.Hosting.Server.Features; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http.Extensions; using Microsoft.AspNetCore.Testing.xunit; @@ -16,20 +21,36 @@ namespace Microsoft.AspNetCore.Server.Kestrel.FunctionalTests { public class AddressRegistrationTests { + [Theory, MemberData(nameof(AddressRegistrationDataIPv4))] - public async Task RegisterAddresses_IPv4_Success(string addressInput, string[] testUrls) + public async Task RegisterAddresses_IPv4_Success(string addressInput, Func testUrls) + { + await RegisterAddresses_Success(addressInput, testUrls); + } + + [ConditionalTheory, MemberData(nameof(AddressRegistrationDataIPv4Port80))] + [Port80SupportedCondition] + public async Task RegisterAddresses_IPv4Port80_Success(string addressInput, Func testUrls) { await RegisterAddresses_Success(addressInput, testUrls); } [ConditionalTheory, MemberData(nameof(AddressRegistrationDataIPv6))] [IPv6SupportedCondition] - public async Task RegisterAddresses_IPv6_Success(string addressInput, string[] testUrls) + public async Task RegisterAddresses_IPv6_Success(string addressInput, Func testUrls) { await RegisterAddresses_Success(addressInput, testUrls); } - public async Task RegisterAddresses_Success(string addressInput, string[] testUrls) + [ConditionalTheory, MemberData(nameof(AddressRegistrationDataIPv6ScopeId))] + [OSSkipCondition(OperatingSystems.Linux, SkipReason = "HttpClient does not support IPv6 with scope ID on Linux (https://github.com/dotnet/corefx/issues/8235).")] + [OSSkipCondition(OperatingSystems.MacOSX, SkipReason = "HttpClient does not support IPv6 with scope ID on Mac (https://github.com/dotnet/corefx/issues/8235).")] + public async Task RegisterAddresses_IPv6ScopeId_Success(string addressInput, Func testUrls) + { + await RegisterAddresses_Success(addressInput, testUrls); + } + + public async Task RegisterAddresses_Success(string addressInput, Func testUrls) { var config = new ConfigurationBuilder() .AddInMemoryCollection(new Dictionary @@ -49,49 +70,129 @@ namespace Microsoft.AspNetCore.Server.Kestrel.FunctionalTests using (var client = new HttpClient()) { - foreach (var testUrl in testUrls) + foreach (var testUrl in testUrls(host.ServerFeatures.Get())) { - var responseText = await client.GetStringAsync(testUrl); - Assert.Equal(testUrl, responseText); + var response = await client.GetAsync(testUrl); + + // Compare the response with the RequestMessage.RequestUri, rather than testUrl directly. + // Required to handle IPv6 addresses with zone index, like "fe80::3%1" + Assert.Equal( + response.RequestMessage.RequestUri.ToString(), + await response.Content.ReadAsStringAsync()); } } } } - public static TheoryData AddressRegistrationDataIPv4 + public static TheoryData> AddressRegistrationDataIPv4 { get { - var port1 = PortManager.GetPort(); - var port2 = PortManager.GetPort(); - var dataset = new TheoryData(); - dataset.Add($"{port1}", new[] { $"http://localhost:{port1}/" }); - dataset.Add($"{port1};{port2}", new[] { $"http://localhost:{port1}/", $"http://localhost:{port2}/" }); - dataset.Add($"http://127.0.0.1:{port1}/", new[] { $"http://127.0.0.1:{port1}/", }); - dataset.Add($"http://localhost:{port1}/base/path", new[] { $"http://localhost:{port1}/base/path" }); + var dataset = new TheoryData>(); + + // Default host and port + dataset.Add(null, _ => new[] { "http://localhost:5000/" }); + dataset.Add(string.Empty, _ => new[] { "http://localhost:5000/" }); + + // Static port + var port1 = GetNextPort(); + var port2 = GetNextPort(); + dataset.Add($"{port1}", _ => new[] { $"http://localhost:{port1}/" }); + dataset.Add($"{port1};{port2}", _ => new[] { $"http://localhost:{port1}/", $"http://localhost:{port2}/" }); + + // Ensure "localhost" and "127.0.0.1" are equivalent + dataset.Add($"http://localhost:{port1}", _ => new[] { $"http://localhost:{port1}/", $"http://127.0.0.1:{port1}/" }); + dataset.Add($"http://127.0.0.1:{port1}", _ => new[] { $"http://localhost:{port1}/", $"http://127.0.0.1:{port1}/" }); + + // Path after port + dataset.Add($"http://localhost:{port1}/base/path", _ => new[] { $"http://localhost:{port1}/base/path" }); + + // Dynamic port + dataset.Add("0", GetTestUrls); + dataset.Add("http://localhost:0/", GetTestUrls); + dataset.Add($"http://{Dns.GetHostName()}:0/", GetTestUrls); + + var ipv4Addresses = Dns.GetHostAddressesAsync(Dns.GetHostName()).Result + .Where(ip => ip.AddressFamily == AddressFamily.InterNetwork); + foreach (var ip in ipv4Addresses) + { + dataset.Add($"http://{ip}:0/", GetTestUrls); + } return dataset; } } - public static TheoryData AddressRegistrationDataIPv6 + public static TheoryData> AddressRegistrationDataIPv4Port80 { get { - var port = PortManager.GetPort(); - var dataset = new TheoryData(); - dataset.Add($"http://*:{port}/", new[] { $"http://localhost:{port}/", $"http://127.0.0.1:{port}/", $"http://[::1]:{port}/" }); - dataset.Add($"http://localhost:{port}/", new[] { $"http://localhost:{port}/", $"http://127.0.0.1:{port}/", - /* // https://github.com/aspnet/KestrelHttpServer/issues/231 - $"http://[::1]:{port}/" - */ }); - dataset.Add($"http://[::1]:{port}/", new[] { $"http://[::1]:{port}/", }); - dataset.Add($"http://127.0.0.1:{port}/;http://[::1]:{port}/", new[] { $"http://127.0.0.1:{port}/", $"http://[::1]:{port}/" }); + var dataset = new TheoryData>(); + + // Default port for HTTP (80) + dataset.Add("http://*", _ => new[] { "http://localhost/" }); + dataset.Add("http://localhost", _ => new[] { "http://localhost/" }); return dataset; } } + public static TheoryData> AddressRegistrationDataIPv6 + { + get + { + var dataset = new TheoryData>(); + + // Static port + var port = GetNextPort(); + dataset.Add($"http://*:{port}/", _ => new[] { $"http://localhost:{port}/", $"http://127.0.0.1:{port}/", $"http://[::1]:{port}/" }); + dataset.Add($"http://localhost:{port}/", _ => new[] { $"http://localhost:{port}/", $"http://127.0.0.1:{port}/", + /* // https://github.com/aspnet/KestrelHttpServer/issues/231 + $"http://[::1]:{port}/" + */ }); + dataset.Add($"http://[::1]:{port}/", _ => new[] { $"http://[::1]:{port}/", }); + dataset.Add($"http://127.0.0.1:{port}/;http://[::1]:{port}/", _ => new[] { $"http://127.0.0.1:{port}/", $"http://[::1]:{port}/" }); + + // Dynamic port + var ipv6Addresses = Dns.GetHostAddressesAsync(Dns.GetHostName()).Result + .Where(ip => ip.AddressFamily == AddressFamily.InterNetworkV6) + .Where(ip => ip.ScopeId == 0); + foreach (var ip in ipv6Addresses) + { + dataset.Add($"http://[{ip}]:0/", GetTestUrls); + } + + return dataset; + } + } + + public static TheoryData> AddressRegistrationDataIPv6ScopeId + { + get + { + var dataset = new TheoryData>(); + + // Dynamic port + var ipv6Addresses = Dns.GetHostAddressesAsync(Dns.GetHostName()).Result + .Where(ip => ip.AddressFamily == AddressFamily.InterNetworkV6) + .Where(ip => ip.ScopeId != 0); + foreach (var ip in ipv6Addresses) + { + dataset.Add($"http://[{ip}]:0/", GetTestUrls); + } + + return dataset; + } + } + + private static string[] GetTestUrls(IServerAddressesFeature addressesFeature) + { + return addressesFeature.Addresses + .Select(a => a.Replace("://+", "://localhost")) + .Select(a => a.EndsWith("/") ? a : a + "/") + .ToArray(); + } + private void ConfigureEchoAddress(IApplicationBuilder app) { app.Run(context => @@ -99,5 +200,72 @@ namespace Microsoft.AspNetCore.Server.Kestrel.FunctionalTests return context.Response.WriteAsync(context.Request.GetDisplayUrl()); }); } + + private static int _nextPort = 8001; + private static object _portLock = new object(); + private static int GetNextPort() + { + lock (_portLock) + { + using (var socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp)) + { + while (true) + { + try + { + var port = _nextPort++; + socket.Bind(new IPEndPoint(IPAddress.Loopback, port)); + return port; + } + catch (SocketException) + { + // Retry unless exhausted + if (_nextPort == 65536) + { + throw; + } + } + } + } + } + } + + [AttributeUsage(AttributeTargets.Method, AllowMultiple = false)] + private class Port80SupportedConditionAttribute : Attribute, ITestCondition + { + private static readonly Lazy _port80Supported = new Lazy(CanBindToPort80); + + public bool IsMet + { + get + { + return _port80Supported.Value; + } + } + + public string SkipReason + { + get + { + return "Cannot bind to port 80 on the host."; + } + } + + private static bool CanBindToPort80() + { + try + { + using (var socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp)) + { + socket.Bind(new IPEndPoint(IPAddress.Loopback, 80)); + return true; + } + } + catch (SocketException) + { + return false; + } + } + } } } diff --git a/test/Microsoft.AspNetCore.Server.Kestrel.FunctionalTests/IWebHostPortExtensions.cs b/test/Microsoft.AspNetCore.Server.Kestrel.FunctionalTests/IWebHostPortExtensions.cs new file mode 100644 index 0000000000..9b3509503e --- /dev/null +++ b/test/Microsoft.AspNetCore.Server.Kestrel.FunctionalTests/IWebHostPortExtensions.cs @@ -0,0 +1,25 @@ +// 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.ServerFeatures.Get().Addresses + .Select(a => a.Replace("://+", "://localhost")) + .Select(a => (new Uri(a)).Port); + } + } +} diff --git a/test/Microsoft.AspNetCore.Server.Kestrel.FunctionalTests/PathBaseTests.cs b/test/Microsoft.AspNetCore.Server.Kestrel.FunctionalTests/PathBaseTests.cs index 12baa2731d..6520d73eb5 100644 --- a/test/Microsoft.AspNetCore.Server.Kestrel.FunctionalTests/PathBaseTests.cs +++ b/test/Microsoft.AspNetCore.Server.Kestrel.FunctionalTests/PathBaseTests.cs @@ -68,10 +68,9 @@ namespace Microsoft.AspNetCore.Server.Kestrel.FunctionalTests private async Task TestPathBase(string registerPathBase, string requestPath, string expectedPathBase, string expectedPath) { - var port = PortManager.GetPort(); var config = new ConfigurationBuilder().AddInMemoryCollection( new Dictionary { - { "server.urls", $"http://localhost:{port}{registerPathBase}" } + { "server.urls", $"http://localhost:0{registerPathBase}" } }).Build(); var builder = new WebHostBuilder() @@ -95,7 +94,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.FunctionalTests using (var client = new HttpClient()) { - var response = await client.GetAsync($"http://localhost:{port}{requestPath}"); + var response = await client.GetAsync($"http://localhost:{host.GetPort()}{requestPath}"); response.EnsureSuccessStatusCode(); var responseText = await response.Content.ReadAsStringAsync(); diff --git a/test/Microsoft.AspNetCore.Server.Kestrel.FunctionalTests/PortManager.cs b/test/Microsoft.AspNetCore.Server.Kestrel.FunctionalTests/PortManager.cs deleted file mode 100644 index 62e019d4be..0000000000 --- a/test/Microsoft.AspNetCore.Server.Kestrel.FunctionalTests/PortManager.cs +++ /dev/null @@ -1,15 +0,0 @@ -// 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.Threading; - -namespace Microsoft.AspNetCore.Server.Kestrel.FunctionalTests -{ - public static class PortManager - { - public static int GetPort() - { - return TestCommon.PortManager.GetNextPort(); - } - } -} diff --git a/test/Microsoft.AspNetCore.Server.Kestrel.FunctionalTests/RequestTests.cs b/test/Microsoft.AspNetCore.Server.Kestrel.FunctionalTests/RequestTests.cs index 63f4415042..3a032767ac 100644 --- a/test/Microsoft.AspNetCore.Server.Kestrel.FunctionalTests/RequestTests.cs +++ b/test/Microsoft.AspNetCore.Server.Kestrel.FunctionalTests/RequestTests.cs @@ -22,10 +22,9 @@ namespace Microsoft.AspNetCore.Server.Kestrel.FunctionalTests [Fact] public async Task LargeUpload() { - var port = PortManager.GetPort(); var builder = new WebHostBuilder() .UseKestrel() - .UseUrls($"http://localhost:{port}/") + .UseUrls($"http://localhost:0/") .Configure(app => { app.Run(async context => @@ -60,7 +59,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.FunctionalTests bytes[i] = (byte)i; } - var response = await client.PostAsync($"http://localhost:{port}/", new ByteArrayContent(bytes)); + var response = await client.PostAsync($"http://localhost:{host.GetPort()}/", new ByteArrayContent(bytes)); response.EnsureSuccessStatusCode(); var sizeString = await response.Content.ReadAsStringAsync(); Assert.Equal(sizeString, bytes.Length.ToString(CultureInfo.InvariantCulture)); @@ -72,10 +71,9 @@ namespace Microsoft.AspNetCore.Server.Kestrel.FunctionalTests [FrameworkSkipCondition(RuntimeFrameworks.Mono, SkipReason = "Fails on Mono on Mac because it is not 64-bit.")] public async Task LargeMultipartUpload() { - var port = PortManager.GetPort(); var builder = new WebHostBuilder() .UseKestrel() - .UseUrls($"http://localhost:{port}/") + .UseUrls($"http://localhost:0/") .Configure(app => { app.Run(async context => @@ -111,7 +109,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.FunctionalTests } var length = form.Headers.ContentLength.Value; - var response = await client.PostAsync($"http://localhost:{port}/", form); + var response = await client.PostAsync($"http://localhost:{host.GetPort()}/", form); response.EnsureSuccessStatusCode(); Assert.Equal(length.ToString(CultureInfo.InvariantCulture), await response.Content.ReadAsStringAsync()); } @@ -137,10 +135,9 @@ namespace Microsoft.AspNetCore.Server.Kestrel.FunctionalTests [Fact] public async Task DoesNotHangOnConnectionCloseRequest() { - var port = PortManager.GetPort(); var builder = new WebHostBuilder() .UseKestrel() - .UseUrls($"http://localhost:{port}") + .UseUrls($"http://localhost:0") .Configure(app => { app.Run(async context => @@ -158,7 +155,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.FunctionalTests client.DefaultRequestHeaders.Connection.Clear(); client.DefaultRequestHeaders.Connection.Add("close"); - var response = await client.GetAsync($"http://localhost:{port}/"); + var response = await client.GetAsync($"http://localhost:{host.GetPort()}/"); response.EnsureSuccessStatusCode(); } } @@ -166,10 +163,9 @@ namespace Microsoft.AspNetCore.Server.Kestrel.FunctionalTests [Fact] public void RequestPathIsNormalized() { - var port = PortManager.GetPort(); var builder = new WebHostBuilder() .UseKestrel() - .UseUrls($"http://localhost:{port}/\u0041\u030A") + .UseUrls($"http://localhost:0/\u0041\u030A") .Configure(app => { app.Run(async context => @@ -185,7 +181,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.FunctionalTests { host.Start(); - using (var socket = TestConnection.CreateConnectedLoopbackSocket(port)) + using (var socket = TestConnection.CreateConnectedLoopbackSocket(host.GetPort())) { socket.Send(Encoding.ASCII.GetBytes("GET /%41%CC%8A/A/../B/%41%CC%8A HTTP/1.1\r\n\r\n")); socket.Shutdown(SocketShutdown.Send); @@ -210,10 +206,9 @@ namespace Microsoft.AspNetCore.Server.Kestrel.FunctionalTests private async Task TestRemoteIPAddress(string registerAddress, string requestAddress, string expectAddress) { - var port = PortManager.GetPort(); var builder = new WebHostBuilder() .UseKestrel() - .UseUrls($"http://{registerAddress}:{port}") + .UseUrls($"http://{registerAddress}:0") .Configure(app => { app.Run(async context => @@ -234,7 +229,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.FunctionalTests { host.Start(); - var response = await client.GetAsync($"http://{requestAddress}:{port}/"); + var response = await client.GetAsync($"http://{requestAddress}:{host.GetPort()}/"); response.EnsureSuccessStatusCode(); var connectionFacts = await response.Content.ReadAsStringAsync(); diff --git a/test/Microsoft.AspNetCore.Server.Kestrel.FunctionalTests/ResponseTests.cs b/test/Microsoft.AspNetCore.Server.Kestrel.FunctionalTests/ResponseTests.cs index a1dfe66ab1..2d3c70aff2 100644 --- a/test/Microsoft.AspNetCore.Server.Kestrel.FunctionalTests/ResponseTests.cs +++ b/test/Microsoft.AspNetCore.Server.Kestrel.FunctionalTests/ResponseTests.cs @@ -21,11 +21,10 @@ namespace Microsoft.AspNetCore.Server.Kestrel.FunctionalTests [Fact] public async Task LargeDownload() { - var port = PortManager.GetPort(); var config = new ConfigurationBuilder() .AddInMemoryCollection(new Dictionary { - { "server.urls", $"http://localhost:{port}/" } + { "server.urls", $"http://localhost:0/" } }) .Build(); @@ -57,7 +56,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.FunctionalTests using (var client = new HttpClient()) { - var response = await client.GetAsync($"http://localhost:{port}/"); + var response = await client.GetAsync($"http://localhost:{host.GetPort()}/"); response.EnsureSuccessStatusCode(); var responseBody = await response.Content.ReadAsStreamAsync(); @@ -81,11 +80,10 @@ namespace Microsoft.AspNetCore.Server.Kestrel.FunctionalTests [Theory, MemberData(nameof(NullHeaderData))] public async Task IgnoreNullHeaderValues(string headerName, StringValues headerValue, string expectedValue) { - var port = PortManager.GetPort(); var config = new ConfigurationBuilder() .AddInMemoryCollection(new Dictionary { - { "server.urls", $"http://localhost:{port}/" } + { "server.urls", $"http://localhost:0/" } }) .Build(); @@ -108,7 +106,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.FunctionalTests using (var client = new HttpClient()) { - var response = await client.GetAsync($"http://localhost:{port}/"); + var response = await client.GetAsync($"http://localhost:{host.GetPort()}/"); response.EnsureSuccessStatusCode(); var headers = response.Headers; @@ -129,11 +127,10 @@ namespace Microsoft.AspNetCore.Server.Kestrel.FunctionalTests [Fact] public async Task OnCompleteCalledEvenWhenOnStartingNotCalled() { - var port = PortManager.GetPort(); var config = new ConfigurationBuilder() .AddInMemoryCollection(new Dictionary { - { "server.urls", $"http://localhost:{port}/" } + { "server.urls", $"http://localhost:0/" } }) .Build(); @@ -161,7 +158,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.FunctionalTests using (var client = new HttpClient()) { - var response = await client.GetAsync($"http://localhost:{port}/"); + var response = await client.GetAsync($"http://localhost:{host.GetPort()}/"); Assert.Equal(HttpStatusCode.InternalServerError, response.StatusCode); Assert.False(onStartingCalled); diff --git a/test/Microsoft.AspNetCore.Server.Kestrel.FunctionalTests/ThreadCountTests.cs b/test/Microsoft.AspNetCore.Server.Kestrel.FunctionalTests/ThreadCountTests.cs index 543d1d2a4e..2c10fd96a2 100644 --- a/test/Microsoft.AspNetCore.Server.Kestrel.FunctionalTests/ThreadCountTests.cs +++ b/test/Microsoft.AspNetCore.Server.Kestrel.FunctionalTests/ThreadCountTests.cs @@ -16,11 +16,10 @@ namespace Microsoft.AspNetCore.Server.Kestrel.FunctionalTests { public async Task ZeroToTenThreads(int threadCount) { - var port = PortManager.GetPort(); var config = new ConfigurationBuilder() .AddInMemoryCollection(new Dictionary { - { "server.urls", $"http://localhost:{port}/" } + { "server.urls", $"http://localhost:0/" } }) .Build(); @@ -48,7 +47,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.FunctionalTests var requestTasks = new List>(); for (int i = 0; i < 20; i++) { - var requestTask = client.GetStringAsync($"http://localhost:{port}/"); + var requestTask = client.GetStringAsync($"http://localhost:{host.GetPort()}/"); requestTasks.Add(requestTask); } diff --git a/test/Microsoft.AspNetCore.Server.Kestrel.FunctionalTests/project.json b/test/Microsoft.AspNetCore.Server.Kestrel.FunctionalTests/project.json index ca59561e28..35ae2f4011 100644 --- a/test/Microsoft.AspNetCore.Server.Kestrel.FunctionalTests/project.json +++ b/test/Microsoft.AspNetCore.Server.Kestrel.FunctionalTests/project.json @@ -5,7 +5,7 @@ "Microsoft.NETCore.Platforms": "1.0.1-*", "Microsoft.AspNetCore.Http.Abstractions": "1.0.0-*", "Microsoft.AspNetCore.Server.Kestrel": "1.0.0-*", - "Microsoft.AspNetCore.Server.Kestrel.TestCommon": "1.0.0-*", + "Microsoft.AspNetCore.Server.Kestrel.Https": "1.0.0-*", "Microsoft.AspNetCore.Testing": "1.0.0-*", "Newtonsoft.Json": "8.0.3", "xunit": "2.1.0" @@ -18,6 +18,7 @@ "type": "platform" }, "System.Net.Http": "4.0.1-*", + "System.Net.Http.WinHttpHandler": "4.0.0-*", "System.Runtime.Serialization.Primitives": "4.1.1-*" }, "imports": [ diff --git a/test/Microsoft.AspNetCore.Server.Kestrel.TestCommon/Microsoft.AspNetCore.Server.Kestrel.TestCommon.xproj b/test/Microsoft.AspNetCore.Server.Kestrel.TestCommon/Microsoft.AspNetCore.Server.Kestrel.TestCommon.xproj deleted file mode 100644 index fbee634344..0000000000 --- a/test/Microsoft.AspNetCore.Server.Kestrel.TestCommon/Microsoft.AspNetCore.Server.Kestrel.TestCommon.xproj +++ /dev/null @@ -1,17 +0,0 @@ - - - - 14.0 - $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) - - - - a485b4f9-0392-478c-b19a-f4de6b17f491 - ..\..\artifacts\obj\$(MSBuildProjectName) - ..\..\artifacts\bin\ - - - 2.0 - - - \ No newline at end of file diff --git a/test/Microsoft.AspNetCore.Server.Kestrel.TestCommon/PortManager.cs b/test/Microsoft.AspNetCore.Server.Kestrel.TestCommon/PortManager.cs deleted file mode 100644 index a90f229963..0000000000 --- a/test/Microsoft.AspNetCore.Server.Kestrel.TestCommon/PortManager.cs +++ /dev/null @@ -1,38 +0,0 @@ -using System.Net; -using System.Net.Sockets; - -namespace Microsoft.AspNetCore.Server.Kestrel.TestCommon -{ - public static class PortManager - { - public static int _nextPort = 8001; - public static object _portLock = new object(); - - public static int GetNextPort() - { - lock (_portLock) - { - using (var socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp)) - { - while (true) - { - try - { - var port = _nextPort++; - socket.Bind(new IPEndPoint(IPAddress.Loopback, port)); - return port; - } - catch (SocketException) - { - // Retry unless exhausted - if (_nextPort == 65536) - { - throw; - } - } - } - } - } - } - } -} \ No newline at end of file diff --git a/test/Microsoft.AspNetCore.Server.Kestrel.TestCommon/project.json b/test/Microsoft.AspNetCore.Server.Kestrel.TestCommon/project.json deleted file mode 100644 index c6f9341a65..0000000000 --- a/test/Microsoft.AspNetCore.Server.Kestrel.TestCommon/project.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "version": "1.0.0-*", - "frameworks": { - "net451": {}, - "netstandard1.3": { - "dependencies": { - "System.Threading": "4.0.11-*", - "System.Net.Sockets": "4.1.0-*" - }, - "imports": [ - "portable-net45+win8" - ] - } - }, - "buildOptions": { - "keyFile": "../../tools/Key.snk" - } -} \ No newline at end of file diff --git a/test/Microsoft.AspNetCore.Server.KestrelTests/ConnectionTests.cs b/test/Microsoft.AspNetCore.Server.KestrelTests/ConnectionTests.cs index 3b710b508b..97dde60c89 100644 --- a/test/Microsoft.AspNetCore.Server.KestrelTests/ConnectionTests.cs +++ b/test/Microsoft.AspNetCore.Server.KestrelTests/ConnectionTests.cs @@ -27,7 +27,7 @@ namespace Microsoft.AspNetCore.Server.KestrelTests FrameFactory = connectionContext => new Frame( new DummyApplication(httpContext => TaskUtilities.CompletedTask), connectionContext), Memory = memory, - ServerAddress = ServerAddress.FromUrl($"http://localhost:{TestServer.GetNextPort()}"), + ServerAddress = ServerAddress.FromUrl($"http://localhost:0"), Thread = engine.Threads[0] }; var socket = new MockSocket(mockLibuv, Thread.CurrentThread.ManagedThreadId, trace); diff --git a/test/Microsoft.AspNetCore.Server.KestrelTests/EngineTests.cs b/test/Microsoft.AspNetCore.Server.KestrelTests/EngineTests.cs index aadf9361c1..b8bdffeebf 100644 --- a/test/Microsoft.AspNetCore.Server.KestrelTests/EngineTests.cs +++ b/test/Microsoft.AspNetCore.Server.KestrelTests/EngineTests.cs @@ -88,7 +88,7 @@ namespace Microsoft.AspNetCore.Server.KestrelTests testContext.App = App; var engine = new KestrelEngine(testContext); engine.Start(1); - var address = ServerAddress.FromUrl($"http://localhost:{TestServer.GetNextPort()}/"); + var address = ServerAddress.FromUrl($"http://localhost:0/"); var started = engine.CreateServer(address); started.Dispose(); engine.Dispose(); @@ -98,14 +98,13 @@ namespace Microsoft.AspNetCore.Server.KestrelTests [MemberData(nameof(ConnectionFilterData))] public void ConnectionCanReadAndWrite(TestServiceContext testContext) { - var port = TestServer.GetNextPort(); testContext.App = App; var engine = new KestrelEngine(testContext); engine.Start(1); - var address = ServerAddress.FromUrl($"http://localhost:{port}/"); + var address = ServerAddress.FromUrl($"http://localhost:0/"); var started = engine.CreateServer(address); - var socket = TestConnection.CreateConnectedLoopbackSocket(port); + var socket = TestConnection.CreateConnectedLoopbackSocket(address.Port); socket.Send(Encoding.ASCII.GetBytes("POST / HTTP/1.0\r\n\r\nHello World")); socket.Shutdown(SocketShutdown.Send); var buffer = new byte[8192]; diff --git a/test/Microsoft.AspNetCore.Server.KestrelTests/HttpsConnectionFilterTests.cs b/test/Microsoft.AspNetCore.Server.KestrelTests/HttpsConnectionFilterTests.cs index 6666335258..e41bced2e6 100644 --- a/test/Microsoft.AspNetCore.Server.KestrelTests/HttpsConnectionFilterTests.cs +++ b/test/Microsoft.AspNetCore.Server.KestrelTests/HttpsConnectionFilterTests.cs @@ -69,18 +69,17 @@ namespace Microsoft.AspNetCore.Server.KestrelTests var handler = new WinHttpHandler(); handler.ServerCertificateValidationCallback += (sender, cert, chain, sslPolicyErrors) => true; #endif - var serverAddress = $"https://localhost:{TestServer.GetNextPort()}/"; var serviceContext = new TestServiceContext(new HttpsConnectionFilter( new HttpsConnectionFilterOptions { ServerCertificate = new X509Certificate2(@"TestResources/testCert.pfx", "testPassword") }, new NoOpConnectionFilter()) ); - using (var server = new TestServer(App, serviceContext, serverAddress)) + using (var server = new TestServer(App, serviceContext, "https://localhost:0/")) { using (var client = new HttpClient(handler)) { - var result = await client.PostAsync(serverAddress, new FormUrlEncodedContent(new[] { + var result = await client.PostAsync($"https://localhost:{server.Port}/", new FormUrlEncodedContent(new[] { new KeyValuePair("content", "Hello World?") })); @@ -114,7 +113,6 @@ namespace Microsoft.AspNetCore.Server.KestrelTests handler.ServerCertificateValidationCallback += (sender, cert, chain, sslPolicyErrors) => true; #endif - var serverAddress = $"https://localhost:{TestServer.GetNextPort()}/"; var serviceContext = new TestServiceContext(new HttpsConnectionFilter( new HttpsConnectionFilterOptions { @@ -124,12 +122,12 @@ namespace Microsoft.AspNetCore.Server.KestrelTests new NoOpConnectionFilter()) ); - using (var server = new TestServer(App, serviceContext, serverAddress)) + using (var server = new TestServer(App, serviceContext, "https://localhost:0/")) { using (var client = new HttpClient(handler)) { await Assert.ThrowsAnyAsync( - () => client.GetAsync(serverAddress)); + () => client.GetAsync($"https://localhost:{server.Port}/")); } } } @@ -159,7 +157,6 @@ namespace Microsoft.AspNetCore.Server.KestrelTests handler.ServerCertificateValidationCallback += (sender, cert, chain, sslPolicyErrors) => true; #endif - var serverAddress = $"https://localhost:{TestServer.GetNextPort()}/"; var serviceContext = new TestServiceContext(new HttpsConnectionFilter( new HttpsConnectionFilterOptions { @@ -175,11 +172,11 @@ namespace Microsoft.AspNetCore.Server.KestrelTests return context.Response.WriteAsync("hello world"); }; - using (var server = new TestServer(app, serviceContext, serverAddress)) + using (var server = new TestServer(app, serviceContext, "https://localhost:0/")) { using (var client = new HttpClient(handler)) { - var result = await client.GetAsync(serverAddress); + var result = await client.GetAsync($"https://localhost:{server.Port}/"); Assert.Equal("hello world", await result.Content.ReadAsStringAsync()); } @@ -206,7 +203,6 @@ namespace Microsoft.AspNetCore.Server.KestrelTests ServicePointManager.ServerCertificateValidationCallback += validationCallback; #endif - var serverAddress = $"https://localhost:{TestServer.GetNextPort()}/"; var serviceContext = new TestServiceContext(new HttpsConnectionFilter( new HttpsConnectionFilterOptions { @@ -226,7 +222,7 @@ namespace Microsoft.AspNetCore.Server.KestrelTests return context.Response.WriteAsync("hello world"); }; - using (var server = new TestServer(app, serviceContext, serverAddress)) + using (var server = new TestServer(app, serviceContext, "https://localhost:0/")) { // SslStream is used to ensure the certificate is actually passed to the server // HttpClient might not send the certificate because it is invalid or it doesn't match any @@ -274,7 +270,6 @@ namespace Microsoft.AspNetCore.Server.KestrelTests handler.ServerCertificateValidationCallback += (sender, cert, chain, sslPolicyErrors) => true; #endif - var serverAddress = $"https://localhost:{TestServer.GetNextPort()}/"; var serviceContext = new TestServiceContext( new HttpsConnectionFilter( new HttpsConnectionFilterOptions @@ -286,11 +281,11 @@ namespace Microsoft.AspNetCore.Server.KestrelTests RequestDelegate app = context => context.Response.WriteAsync(context.Request.Scheme); - using (var server = new TestServer(app, serviceContext, serverAddress)) + using (var server = new TestServer(app, serviceContext, "https://localhost:0/")) { using (var client = new HttpClient(handler)) { - var result = await client.GetAsync(serverAddress); + var result = await client.GetAsync($"https://localhost:{server.Port}/"); Assert.Equal("https", await result.Content.ReadAsStringAsync()); } @@ -317,7 +312,6 @@ namespace Microsoft.AspNetCore.Server.KestrelTests ServicePointManager.ServerCertificateValidationCallback += validationCallback; #endif - var serverAddress = $"https://localhost:{TestServer.GetNextPort()}/"; var serviceContext = new TestServiceContext(new HttpsConnectionFilter( new HttpsConnectionFilterOptions { @@ -333,7 +327,7 @@ namespace Microsoft.AspNetCore.Server.KestrelTests return context.Response.WriteAsync("hello world"); }; - using (var server = new TestServer(app, serviceContext, serverAddress)) + using (var server = new TestServer(app, serviceContext, "https://localhost:0/")) { // SslStream is used to ensure the certificate is actually passed to the server // HttpClient might not send the certificate because it is invalid or it doesn't match any diff --git a/test/Microsoft.AspNetCore.Server.KestrelTests/MultipleLoopTests.cs b/test/Microsoft.AspNetCore.Server.KestrelTests/MultipleLoopTests.cs index af50bba928..ead65ada56 100644 --- a/test/Microsoft.AspNetCore.Server.KestrelTests/MultipleLoopTests.cs +++ b/test/Microsoft.AspNetCore.Server.KestrelTests/MultipleLoopTests.cs @@ -128,7 +128,6 @@ namespace Microsoft.AspNetCore.Server.KestrelTests { var pipeName = @"\\.\pipe\ServerPipeDispatchConnections" + Guid.NewGuid().ToString("n"); - var port = TestServer.GetNextPort(); var loop = new UvLoopHandle(_logger); loop.Init(_uv); @@ -158,8 +157,9 @@ namespace Microsoft.AspNetCore.Server.KestrelTests var serverListenTcp = new UvTcpHandle(_logger); serverListenTcp.Init(loop, (a, b) => { }); - var address = ServerAddress.FromUrl($"http://localhost:{port}/"); + var address = ServerAddress.FromUrl($"http://localhost:0/"); serverListenTcp.Bind(address); + var port = serverListenTcp.GetSockIPEndPoint().Port; serverListenTcp.Listen(128, (_1, status, error, _2) => { var serverConnectionTcp = new UvTcpHandle(_logger); diff --git a/test/Microsoft.AspNetCore.Server.KestrelTests/NetworkingTests.cs b/test/Microsoft.AspNetCore.Server.KestrelTests/NetworkingTests.cs index dd5c5044fc..d1baa5c785 100644 --- a/test/Microsoft.AspNetCore.Server.KestrelTests/NetworkingTests.cs +++ b/test/Microsoft.AspNetCore.Server.KestrelTests/NetworkingTests.cs @@ -76,9 +76,9 @@ namespace Microsoft.AspNetCore.Server.KestrelTests loop.Init(_uv); var tcp = new UvTcpHandle(_logger); tcp.Init(loop, (a, b) => { }); - var port = TestServer.GetNextPort(); - var address = ServerAddress.FromUrl($"http://localhost:{port}/"); + var address = ServerAddress.FromUrl($"http://localhost:0/"); tcp.Bind(address); + var port = tcp.GetSockIPEndPoint().Port; tcp.Listen(10, (stream, status, error, state) => { var tcp2 = new UvTcpHandle(_logger); @@ -105,9 +105,9 @@ namespace Microsoft.AspNetCore.Server.KestrelTests loop.Init(_uv); var tcp = new UvTcpHandle(_logger); tcp.Init(loop, (a, b) => { }); - var port = TestServer.GetNextPort(); - var address = ServerAddress.FromUrl($"http://localhost:{port}/"); + var address = ServerAddress.FromUrl($"http://localhost:0/"); tcp.Bind(address); + var port = tcp.GetSockIPEndPoint().Port; tcp.Listen(10, (_, status, error, state) => { var tcp2 = new UvTcpHandle(_logger); @@ -155,9 +155,9 @@ namespace Microsoft.AspNetCore.Server.KestrelTests loop.Init(_uv); var tcp = new UvTcpHandle(_logger); tcp.Init(loop, (a, b) => { }); - var port = TestServer.GetNextPort(); - var address = ServerAddress.FromUrl($"http://localhost:{port}/"); + var address = ServerAddress.FromUrl($"http://localhost:0/"); tcp.Bind(address); + var port = tcp.GetSockIPEndPoint().Port; tcp.Listen(10, (_, status, error, state) => { var tcp2 = new UvTcpHandle(_logger); diff --git a/test/Microsoft.AspNetCore.Server.KestrelTests/ServerAddressFacts.cs b/test/Microsoft.AspNetCore.Server.KestrelTests/ServerAddressFacts.cs index c29a1fdb15..d9beaa05b3 100644 --- a/test/Microsoft.AspNetCore.Server.KestrelTests/ServerAddressFacts.cs +++ b/test/Microsoft.AspNetCore.Server.KestrelTests/ServerAddressFacts.cs @@ -19,27 +19,28 @@ namespace Microsoft.AspNetCore.Server.KestrelTests } [Theory] - [InlineData("://emptyscheme", "", "emptyscheme", 0, "")] - [InlineData("http://localhost", "http", "localhost", 80, "")] - [InlineData("http://www.example.com", "http", "www.example.com", 80, "")] - [InlineData("https://www.example.com", "https", "www.example.com", 443, "")] - [InlineData("http://www.example.com/", "http", "www.example.com", 80, "")] - [InlineData("http://www.example.com/foo?bar=baz", "http", "www.example.com", 80, "/foo?bar=baz")] - [InlineData("http://www.example.com:5000", "http", "www.example.com", 5000, "")] - [InlineData("https://www.example.com:5000", "https", "www.example.com", 5000, "")] - [InlineData("http://www.example.com:5000/", "http", "www.example.com", 5000, "")] - [InlineData("http://www.example.com:NOTAPORT", "http", "www.example.com:NOTAPORT", 80, "")] - [InlineData("https://www.example.com:NOTAPORT", "https", "www.example.com:NOTAPORT", 443, "")] - [InlineData("http://www.example.com:NOTAPORT/", "http", "www.example.com:NOTAPORT", 80, "")] - [InlineData("http://foo:/tmp/kestrel-test.sock:5000/doesn't/matter", "http", "foo:", 80, "/tmp/kestrel-test.sock:5000/doesn't/matter")] - [InlineData("http://unix:foo/tmp/kestrel-test.sock", "http", "unix:foo", 80, "/tmp/kestrel-test.sock")] - [InlineData("http://unix:5000/tmp/kestrel-test.sock", "http", "unix", 5000, "/tmp/kestrel-test.sock")] - [InlineData("http://unix:/tmp/kestrel-test.sock", "http", "unix:/tmp/kestrel-test.sock", 0, "")] - [InlineData("https://unix:/tmp/kestrel-test.sock", "https", "unix:/tmp/kestrel-test.sock", 0, "")] - [InlineData("http://unix:/tmp/kestrel-test.sock:", "http", "unix:/tmp/kestrel-test.sock", 0, "")] - [InlineData("http://unix:/tmp/kestrel-test.sock:/", "http", "unix:/tmp/kestrel-test.sock", 0, "")] - [InlineData("http://unix:/tmp/kestrel-test.sock:5000/doesn't/matter", "http", "unix:/tmp/kestrel-test.sock", 0, "5000/doesn't/matter")] - public void UrlsAreParsedCorrectly(string url, string scheme, string host, int port, string pathBase) + [InlineData("5000", "http", "+", 5000, "/", "http://+:5000/")] + [InlineData("://emptyscheme", "", "emptyscheme", 0, "", "://emptyscheme:0")] + [InlineData("http://localhost", "http", "localhost", 80, "", "http://localhost:80")] + [InlineData("http://www.example.com", "http", "www.example.com", 80, "", "http://www.example.com:80")] + [InlineData("https://www.example.com", "https", "www.example.com", 443, "", "https://www.example.com:443")] + [InlineData("http://www.example.com/", "http", "www.example.com", 80, "", "http://www.example.com:80")] + [InlineData("http://www.example.com/foo?bar=baz", "http", "www.example.com", 80, "/foo?bar=baz", "http://www.example.com:80/foo?bar=baz")] + [InlineData("http://www.example.com:5000", "http", "www.example.com", 5000, "", null)] + [InlineData("https://www.example.com:5000", "https", "www.example.com", 5000, "", null)] + [InlineData("http://www.example.com:5000/", "http", "www.example.com", 5000, "", "http://www.example.com:5000")] + [InlineData("http://www.example.com:NOTAPORT", "http", "www.example.com:NOTAPORT", 80, "", "http://www.example.com:notaport:80")] + [InlineData("https://www.example.com:NOTAPORT", "https", "www.example.com:NOTAPORT", 443, "", "https://www.example.com:notaport:443")] + [InlineData("http://www.example.com:NOTAPORT/", "http", "www.example.com:NOTAPORT", 80, "", "http://www.example.com:notaport:80")] + [InlineData("http://foo:/tmp/kestrel-test.sock:5000/doesn't/matter", "http", "foo:", 80, "/tmp/kestrel-test.sock:5000/doesn't/matter", "http://foo::80/tmp/kestrel-test.sock:5000/doesn't/matter")] + [InlineData("http://unix:foo/tmp/kestrel-test.sock", "http", "unix:foo", 80, "/tmp/kestrel-test.sock", "http://unix:foo:80/tmp/kestrel-test.sock")] + [InlineData("http://unix:5000/tmp/kestrel-test.sock", "http", "unix", 5000, "/tmp/kestrel-test.sock", null)] + [InlineData("http://unix:/tmp/kestrel-test.sock", "http", "unix:/tmp/kestrel-test.sock", 0, "", null)] + [InlineData("https://unix:/tmp/kestrel-test.sock", "https", "unix:/tmp/kestrel-test.sock", 0, "", null)] + [InlineData("http://unix:/tmp/kestrel-test.sock:", "http", "unix:/tmp/kestrel-test.sock", 0, "", "http://unix:/tmp/kestrel-test.sock")] + [InlineData("http://unix:/tmp/kestrel-test.sock:/", "http", "unix:/tmp/kestrel-test.sock", 0, "", "http://unix:/tmp/kestrel-test.sock")] + [InlineData("http://unix:/tmp/kestrel-test.sock:5000/doesn't/matter", "http", "unix:/tmp/kestrel-test.sock", 0, "5000/doesn't/matter", null)] + public void UrlsAreParsedCorrectly(string url, string scheme, string host, int port, string pathBase, string toString) { var serverAddress = ServerAddress.FromUrl(url); @@ -47,6 +48,8 @@ namespace Microsoft.AspNetCore.Server.KestrelTests Assert.Equal(host, serverAddress.Host); Assert.Equal(port, serverAddress.Port); Assert.Equal(pathBase, serverAddress.PathBase); + + Assert.Equal(toString ?? url, serverAddress.ToString()); } [Fact] diff --git a/test/Microsoft.AspNetCore.Server.KestrelTests/TestServer.cs b/test/Microsoft.AspNetCore.Server.KestrelTests/TestServer.cs index 69b876cbf1..c041f5f437 100644 --- a/test/Microsoft.AspNetCore.Server.KestrelTests/TestServer.cs +++ b/test/Microsoft.AspNetCore.Server.KestrelTests/TestServer.cs @@ -6,7 +6,6 @@ using System.Threading; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Server.Kestrel; using Microsoft.AspNetCore.Server.Kestrel.Http; -using Microsoft.AspNetCore.Server.Kestrel.TestCommon; namespace Microsoft.AspNetCore.Server.KestrelTests { @@ -25,7 +24,7 @@ namespace Microsoft.AspNetCore.Server.KestrelTests } public TestServer(RequestDelegate app, ServiceContext context) - : this(app, context, $"http://localhost:{GetNextPort()}/") + : this(app, context, "http://localhost:0/") { } @@ -58,10 +57,5 @@ namespace Microsoft.AspNetCore.Server.KestrelTests _server.Dispose(); _engine.Dispose(); } - - public static int GetNextPort() - { - return PortManager.GetNextPort(); - } } } \ No newline at end of file diff --git a/test/Microsoft.AspNetCore.Server.KestrelTests/project.json b/test/Microsoft.AspNetCore.Server.KestrelTests/project.json index 998df18145..6bb0db82a1 100644 --- a/test/Microsoft.AspNetCore.Server.KestrelTests/project.json +++ b/test/Microsoft.AspNetCore.Server.KestrelTests/project.json @@ -5,7 +5,6 @@ "Microsoft.NETCore.Platforms": "1.0.1-*", "Microsoft.AspNetCore.Server.Kestrel": "1.0.0-*", "Microsoft.AspNetCore.Server.Kestrel.Https": "1.0.0-*", - "Microsoft.AspNetCore.Server.Kestrel.TestCommon": "1.0.0-*", "Microsoft.AspNetCore.Testing": "1.0.0-*", "xunit": "2.1.0" },