From 3c79b425f1eafea3c177797ae1ed1354c6ee904e Mon Sep 17 00:00:00 2001 From: Pavel Krymets Date: Wed, 13 Jan 2016 13:48:38 -0800 Subject: [PATCH] Use dynamic ports for all deployers --- .../Common/FreePortHelper.cs | 38 +++++++++++++++++++ .../Deployers/ApplicationDeployer.cs | 2 +- .../Deployers/IISDeployer.cs | 29 +++++--------- .../Deployers/IISExpressDeployer.cs | 12 +++--- .../Deployers/SelfHostDeployer.cs | 10 +++-- 5 files changed, 61 insertions(+), 30 deletions(-) create mode 100644 src/Microsoft.AspNet.Server.Testing/Common/FreePortHelper.cs diff --git a/src/Microsoft.AspNet.Server.Testing/Common/FreePortHelper.cs b/src/Microsoft.AspNet.Server.Testing/Common/FreePortHelper.cs new file mode 100644 index 0000000000..f21ae3d001 --- /dev/null +++ b/src/Microsoft.AspNet.Server.Testing/Common/FreePortHelper.cs @@ -0,0 +1,38 @@ +// 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.Net; +using System.Net.Sockets; + +namespace Microsoft.AspNet.Server.Testing.Common +{ + public static class FreePortHelper + { + public static Uri FindFreeUrl(string urlHint) + { + var uriHint = new Uri(urlHint); + var builder = new UriBuilder(uriHint) + { + Port = FindFreePort(uriHint.Port) + }; + return builder.Uri; + } + + public static int FindFreePort(int initialPort) + { + using (var socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp)) + { + try + { + socket.Bind(new IPEndPoint(IPAddress.Loopback, initialPort)); + } + catch (SocketException) + { + socket.Bind(new IPEndPoint(IPAddress.Loopback, 0)); + } + return ((IPEndPoint)socket.LocalEndPoint).Port; + } + } + } +} diff --git a/src/Microsoft.AspNet.Server.Testing/Deployers/ApplicationDeployer.cs b/src/Microsoft.AspNet.Server.Testing/Deployers/ApplicationDeployer.cs index 8901e08f0d..868f3a6e60 100644 --- a/src/Microsoft.AspNet.Server.Testing/Deployers/ApplicationDeployer.cs +++ b/src/Microsoft.AspNet.Server.Testing/Deployers/ApplicationDeployer.cs @@ -93,7 +93,7 @@ namespace Microsoft.AspNet.Server.Testing protected void DnuPublish(string publishRoot = null) { - DeploymentParameters.PublishedApplicationRootPath = Path.Combine(publishRoot ?? Path.GetTempPath(), Guid.NewGuid().ToString()); + DeploymentParameters.PublishedApplicationRootPath = publishRoot ?? Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString()); var noSource = DeploymentParameters.PublishWithNoSource ? "--no-source" : string.Empty; var command = DeploymentParameters.Command ?? "web"; diff --git a/src/Microsoft.AspNet.Server.Testing/Deployers/IISDeployer.cs b/src/Microsoft.AspNet.Server.Testing/Deployers/IISDeployer.cs index 7edbea1491..f292252842 100644 --- a/src/Microsoft.AspNet.Server.Testing/Deployers/IISDeployer.cs +++ b/src/Microsoft.AspNet.Server.Testing/Deployers/IISDeployer.cs @@ -8,6 +8,7 @@ using System.Linq; using System.Net; using System.Net.Sockets; using System.Threading; +using Microsoft.AspNet.Server.Testing.Common; using Microsoft.Extensions.Logging; using Microsoft.Web.Administration; @@ -45,10 +46,12 @@ namespace Microsoft.AspNet.Server.Testing // Drop a json file instead of setting environment variable. SetAspEnvironmentWithJson(); + var uri = FreePortHelper.FindFreeUrl(DeploymentParameters.ApplicationBaseUriHint); + lock (_syncObject) { // To prevent modifying the IIS setup concurrently. - _application.Deploy(); + _application.Deploy(uri); } // Warm up time for IIS setup. @@ -60,7 +63,7 @@ namespace Microsoft.AspNet.Server.Testing WebRootLocation = DeploymentParameters.ApplicationPath, DeploymentParameters = DeploymentParameters, // Accomodate the vdir name. - ApplicationBaseUri = new UriBuilder(Uri.UriSchemeHttp, "localhost", _application.Port).Uri.AbsoluteUri + "/", + ApplicationBaseUri = uri.ToString(), HostShutdownToken = _hostShutdownToken.Token }; } @@ -104,20 +107,16 @@ namespace Microsoft.AspNet.Server.Testing { _deploymentParameters = deploymentParameters; _logger = logger; - WebSiteName = CreateTestSiteName(); - Port = FindFreePort(); } - public int Port { get; } - public string WebSiteName { get; } public string WebSiteRootFolder => $"{Environment.GetEnvironmentVariable("SystemDrive")}\\inetpub\\{WebSiteName}"; - public void Deploy() + public void Deploy(Uri uri) { - _serverManager.Sites.Add(WebSiteName, _deploymentParameters.ApplicationPath, Port); + _serverManager.Sites.Add(WebSiteName, _deploymentParameters.ApplicationPath, uri.Port); _serverManager.CommitChanges(); } @@ -136,25 +135,15 @@ namespace Microsoft.AspNet.Server.Testing _serverManager.CommitChanges(); } } - - private static int FindFreePort() - { - using (var socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp)) - { - socket.Bind(new IPEndPoint(IPAddress.Loopback, 0)); - return ((IPEndPoint)socket.LocalEndPoint).Port; - } - } - private string CreateTestSiteName() { if (!string.IsNullOrEmpty(_deploymentParameters.SiteName)) { - return $"{_deploymentParameters.SiteName}{DateTime.Now.ToString("yyyyMMddHHmmss")}"; + return $"{_deploymentParameters.SiteName}{DateTime.Now.ToString("yyyyMMddHHmmss")}"; } else { - return $"testsite{DateTime.Now.ToString("yyyyMMddHHmmss")}"; + return $"testsite{DateTime.Now.ToString("yyyyMMddHHmmss")}"; } } } diff --git a/src/Microsoft.AspNet.Server.Testing/Deployers/IISExpressDeployer.cs b/src/Microsoft.AspNet.Server.Testing/Deployers/IISExpressDeployer.cs index d3911ac925..7146908c0c 100644 --- a/src/Microsoft.AspNet.Server.Testing/Deployers/IISExpressDeployer.cs +++ b/src/Microsoft.AspNet.Server.Testing/Deployers/IISExpressDeployer.cs @@ -6,6 +6,7 @@ using System.Diagnostics; using System.IO; using System.Threading; using Microsoft.Extensions.Logging; +using Microsoft.AspNet.Server.Testing.Common; namespace Microsoft.AspNet.Server.Testing { @@ -35,20 +36,21 @@ namespace Microsoft.AspNet.Server.Testing DnuPublish(); } + var uri = FreePortHelper.FindFreeUrl(DeploymentParameters.ApplicationBaseUriHint); // Launch the host process. - var hostExitToken = StartIISExpress(); + var hostExitToken = StartIISExpress(uri); return new DeploymentResult { WebRootLocation = DeploymentParameters.ApplicationPath, DeploymentParameters = DeploymentParameters, // Right now this works only for urls like http://localhost:5001/. Does not work for http://localhost:5001/subpath. - ApplicationBaseUri = DeploymentParameters.ApplicationBaseUriHint, + ApplicationBaseUri = uri.ToString(), HostShutdownToken = hostExitToken }; } - private CancellationToken StartIISExpress() + private CancellationToken StartIISExpress(Uri uri) { if (!string.IsNullOrWhiteSpace(DeploymentParameters.ApplicationHostConfigTemplateContent)) { @@ -58,7 +60,7 @@ namespace Microsoft.AspNet.Server.Testing DeploymentParameters.ApplicationHostConfigTemplateContent = DeploymentParameters.ApplicationHostConfigTemplateContent .Replace("[ApplicationPhysicalPath]", DeploymentParameters.ApplicationPath) - .Replace("[PORT]", new Uri(DeploymentParameters.ApplicationBaseUriHint).Port.ToString()); + .Replace("[PORT]", uri.Port.ToString()); DeploymentParameters.ApplicationHostConfigLocation = Path.GetTempFileName(); @@ -72,7 +74,7 @@ namespace Microsoft.AspNet.Server.Testing } var parameters = string.IsNullOrWhiteSpace(DeploymentParameters.ApplicationHostConfigLocation) ? - string.Format("/port:{0} /path:\"{1}\" /trace:error", new Uri(DeploymentParameters.ApplicationBaseUriHint).Port, webroot) : + string.Format("/port:{0} /path:\"{1}\" /trace:error", uri.Port, webroot) : string.Format("/site:{0} /config:{1} /trace:error", DeploymentParameters.SiteName, DeploymentParameters.ApplicationHostConfigLocation); var iisExpressPath = GetIISExpressPath(); diff --git a/src/Microsoft.AspNet.Server.Testing/Deployers/SelfHostDeployer.cs b/src/Microsoft.AspNet.Server.Testing/Deployers/SelfHostDeployer.cs index c018f0dac7..4c502189d7 100644 --- a/src/Microsoft.AspNet.Server.Testing/Deployers/SelfHostDeployer.cs +++ b/src/Microsoft.AspNet.Server.Testing/Deployers/SelfHostDeployer.cs @@ -6,6 +6,7 @@ using System.Diagnostics; using System.IO; using System.Threading; using Microsoft.Extensions.Logging; +using Microsoft.AspNet.Server.Testing.Common; namespace Microsoft.AspNet.Server.Testing { @@ -33,19 +34,20 @@ namespace Microsoft.AspNet.Server.Testing DnuPublish(); } + var uri = FreePortHelper.FindFreeUrl(DeploymentParameters.ApplicationBaseUriHint); // Launch the host process. - var hostExitToken = StartSelfHost(); + var hostExitToken = StartSelfHost(uri); return new DeploymentResult { WebRootLocation = DeploymentParameters.ApplicationPath, DeploymentParameters = DeploymentParameters, - ApplicationBaseUri = DeploymentParameters.ApplicationBaseUriHint, + ApplicationBaseUri = uri.ToString(), HostShutdownToken = hostExitToken }; } - private CancellationToken StartSelfHost() + private CancellationToken StartSelfHost(Uri uri) { var commandName = DeploymentParameters.Command; if (string.IsNullOrEmpty(commandName)) @@ -55,7 +57,7 @@ namespace Microsoft.AspNet.Server.Testing var dnxPath = Path.Combine(TargetRuntimeBinPath, DnxCommandName); var dnxArgs = $"-p \"{DeploymentParameters.ApplicationPath}\" {commandName} " + - $"--server.urls {DeploymentParameters.ApplicationBaseUriHint} " + + $"--server.urls {uri} " + $"--server {(DeploymentParameters.ServerType == ServerType.WebListener ? "Microsoft.AspNet.Server.WebListener" : "Microsoft.AspNet.Server.Kestrel")}"; Logger.LogInformation($"Executing {dnxPath} {dnxArgs}");