Retry TestServer port selection (#1367)
This commit is contained in:
parent
18a718d1f0
commit
5956300df7
|
|
@ -2,6 +2,7 @@
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
|
|
@ -14,7 +15,9 @@ using System.Xml.XPath;
|
||||||
using Microsoft.AspNetCore.Builder;
|
using Microsoft.AspNetCore.Builder;
|
||||||
using Microsoft.AspNetCore.Hosting;
|
using Microsoft.AspNetCore.Hosting;
|
||||||
using Microsoft.AspNetCore.Http;
|
using Microsoft.AspNetCore.Http;
|
||||||
|
using Microsoft.AspNetCore.Http.Extensions;
|
||||||
using Microsoft.AspNetCore.Server.IntegrationTesting;
|
using Microsoft.AspNetCore.Server.IntegrationTesting;
|
||||||
|
using Microsoft.AspNetCore.Server.IntegrationTesting.Common;
|
||||||
using Microsoft.AspNetCore.Server.IntegrationTesting.IIS;
|
using Microsoft.AspNetCore.Server.IntegrationTesting.IIS;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
|
|
@ -29,15 +32,12 @@ namespace Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests
|
||||||
|
|
||||||
internal static string HostableWebCoreLocation => Environment.ExpandEnvironmentVariables($@"%windir%\system32\inetsrv\{HWebCoreDll}");
|
internal static string HostableWebCoreLocation => Environment.ExpandEnvironmentVariables($@"%windir%\system32\inetsrv\{HWebCoreDll}");
|
||||||
internal static string BasePath => Path.GetDirectoryName(new Uri(typeof(TestServer).Assembly.CodeBase).AbsolutePath);
|
internal static string BasePath => Path.GetDirectoryName(new Uri(typeof(TestServer).Assembly.CodeBase).AbsolutePath);
|
||||||
internal static string InProcessHandlerLocation => Path.Combine(BasePath, InProcessHandlerDll);
|
|
||||||
|
|
||||||
internal static string AspNetCoreModuleLocation => Path.Combine(BasePath, AspNetCoreModuleDll);
|
internal static string AspNetCoreModuleLocation => Path.Combine(BasePath, AspNetCoreModuleDll);
|
||||||
|
|
||||||
private static readonly SemaphoreSlim WebCoreLock = new SemaphoreSlim(1, 1);
|
private static readonly SemaphoreSlim WebCoreLock = new SemaphoreSlim(1, 1);
|
||||||
|
|
||||||
// Currently this is hardcoded in HostableWebCore.config
|
private static readonly int PortRetryCount = 10;
|
||||||
private static readonly int BasePort = 50691;
|
|
||||||
private static readonly Uri BaseUri = new Uri("http://localhost:" + BasePort);
|
|
||||||
|
|
||||||
private readonly TaskCompletionSource<object> _startedTaskCompletionSource = new TaskCompletionSource<object>(TaskCreationOptions.RunContinuationsAsynchronously);
|
private readonly TaskCompletionSource<object> _startedTaskCompletionSource = new TaskCompletionSource<object>(TaskCreationOptions.RunContinuationsAsynchronously);
|
||||||
|
|
||||||
|
|
@ -45,23 +45,20 @@ namespace Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests
|
||||||
private readonly ILoggerFactory _loggerFactory;
|
private readonly ILoggerFactory _loggerFactory;
|
||||||
private readonly hostfxr_main_fn _hostfxrMainFn;
|
private readonly hostfxr_main_fn _hostfxrMainFn;
|
||||||
|
|
||||||
public HttpClient HttpClient { get; }
|
private Uri BaseUri => new Uri("http://localhost:" + _currentPort);
|
||||||
public TestConnection CreateConnection() => new TestConnection(BasePort);
|
public HttpClient HttpClient { get; private set; }
|
||||||
|
public TestConnection CreateConnection() => new TestConnection(_currentPort);
|
||||||
|
|
||||||
private IWebHost _host;
|
private IWebHost _host;
|
||||||
|
|
||||||
private string _appHostConfigPath;
|
private string _appHostConfigPath;
|
||||||
|
private int _currentPort;
|
||||||
|
|
||||||
private TestServer(Action<IApplicationBuilder> appBuilder, ILoggerFactory loggerFactory)
|
private TestServer(Action<IApplicationBuilder> appBuilder, ILoggerFactory loggerFactory)
|
||||||
{
|
{
|
||||||
_hostfxrMainFn = Main;
|
_hostfxrMainFn = Main;
|
||||||
_appBuilder = appBuilder;
|
_appBuilder = appBuilder;
|
||||||
_loggerFactory = loggerFactory;
|
_loggerFactory = loggerFactory;
|
||||||
|
|
||||||
HttpClient = new HttpClient(new LoggingHandler(new SocketsHttpHandler(), _loggerFactory.CreateLogger<TestServer>()))
|
|
||||||
{
|
|
||||||
BaseAddress = BaseUri
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static async Task<TestServer> Create(Action<IApplicationBuilder> appBuilder, ILoggerFactory loggerFactory)
|
public static async Task<TestServer> Create(Action<IApplicationBuilder> appBuilder, ILoggerFactory loggerFactory)
|
||||||
|
|
@ -84,18 +81,44 @@ namespace Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests
|
||||||
LoadLibrary(HostableWebCoreLocation);
|
LoadLibrary(HostableWebCoreLocation);
|
||||||
_appHostConfigPath = Path.GetTempFileName();
|
_appHostConfigPath = Path.GetTempFileName();
|
||||||
|
|
||||||
|
set_main_handler(_hostfxrMainFn);
|
||||||
|
|
||||||
|
Retry(() =>
|
||||||
|
{
|
||||||
|
_currentPort = TestPortHelper.GetNextPort();
|
||||||
|
|
||||||
|
InitializeConfig(_currentPort);
|
||||||
|
|
||||||
|
var startResult = WebCoreActivate(_appHostConfigPath, null, "Instance");
|
||||||
|
if (startResult != 0)
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException($"Error while running WebCoreActivate: {startResult} on port {_currentPort}");
|
||||||
|
}
|
||||||
|
}, PortRetryCount);
|
||||||
|
|
||||||
|
HttpClient = new HttpClient(new LoggingHandler(new SocketsHttpHandler(), _loggerFactory.CreateLogger<TestServer>()))
|
||||||
|
{
|
||||||
|
BaseAddress = BaseUri
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private void InitializeConfig(int port)
|
||||||
|
{
|
||||||
var webHostConfig = XDocument.Load(Path.GetFullPath("HostableWebCore.config"));
|
var webHostConfig = XDocument.Load(Path.GetFullPath("HostableWebCore.config"));
|
||||||
webHostConfig.XPathSelectElement("/configuration/system.webServer/globalModules/add[@name='AspNetCoreModuleV2']")
|
webHostConfig.XPathSelectElement("/configuration/system.webServer/globalModules/add[@name='AspNetCoreModuleV2']")
|
||||||
.SetAttributeValue("image", AspNetCoreModuleLocation);
|
.SetAttributeValue("image", AspNetCoreModuleLocation);
|
||||||
|
|
||||||
|
var siteElement = webHostConfig.Root
|
||||||
|
.RequiredElement("system.applicationHost")
|
||||||
|
.RequiredElement("sites")
|
||||||
|
.RequiredElement("site");
|
||||||
|
|
||||||
|
siteElement
|
||||||
|
.RequiredElement("bindings")
|
||||||
|
.RequiredElement("binding")
|
||||||
|
.SetAttributeValue("bindingInformation", $":{port}:localhost");
|
||||||
|
|
||||||
webHostConfig.Save(_appHostConfigPath);
|
webHostConfig.Save(_appHostConfigPath);
|
||||||
|
|
||||||
set_main_handler(_hostfxrMainFn);
|
|
||||||
|
|
||||||
var startResult = WebCoreActivate(_appHostConfigPath, null, "Instance");
|
|
||||||
if (startResult != 0)
|
|
||||||
{
|
|
||||||
throw new InvalidOperationException($"Error while running WebCoreActivate: {startResult}");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private int Main(IntPtr argc, IntPtr argv)
|
private int Main(IntPtr argc, IntPtr argv)
|
||||||
|
|
@ -157,5 +180,25 @@ namespace Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests
|
||||||
|
|
||||||
[DllImport("kernel32", SetLastError=true, CharSet = CharSet.Ansi)]
|
[DllImport("kernel32", SetLastError=true, CharSet = CharSet.Ansi)]
|
||||||
private static extern IntPtr LoadLibrary([MarshalAs(UnmanagedType.LPStr)] string lpFileName);
|
private static extern IntPtr LoadLibrary([MarshalAs(UnmanagedType.LPStr)] string lpFileName);
|
||||||
|
|
||||||
|
private void Retry(Action func, int attempts)
|
||||||
|
{
|
||||||
|
var exceptions = new List<Exception>();
|
||||||
|
|
||||||
|
for (var attempt = 0; attempt < attempts; attempt++)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
func();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
exceptions.Add(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new AggregateException(exceptions);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue