Add TestApplication to allow publish output caching (#1511)

This commit is contained in:
Pavel Krymets 2018-07-31 16:36:31 -07:00 коммит произвёл GitHub
Родитель 446b64c199
Коммит 658906bf7c
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
7 изменённых файлов: 333 добавлений и 150 удалений

Просмотреть файл

@ -4,34 +4,34 @@
</PropertyGroup>
<PropertyGroup Label="Package Versions">
<InternalAspNetCoreSdkPackageVersion>2.2.0-preview1-17102</InternalAspNetCoreSdkPackageVersion>
<MicrosoftAspNetCoreHttpAbstractionsPackageVersion>2.2.0-preview1-34823</MicrosoftAspNetCoreHttpAbstractionsPackageVersion>
<MicrosoftAspNetCoreHttpExtensionsPackageVersion>2.2.0-preview1-34823</MicrosoftAspNetCoreHttpExtensionsPackageVersion>
<MicrosoftAspNetCoreHttpFeaturesPackageVersion>2.2.0-preview1-34823</MicrosoftAspNetCoreHttpFeaturesPackageVersion>
<MicrosoftAspNetCoreHttpPackageVersion>2.2.0-preview1-34823</MicrosoftAspNetCoreHttpPackageVersion>
<MicrosoftAspNetCoreOwinPackageVersion>2.2.0-preview1-34823</MicrosoftAspNetCoreOwinPackageVersion>
<MicrosoftAspNetCoreTestingPackageVersion>2.2.0-preview1-34823</MicrosoftAspNetCoreTestingPackageVersion>
<MicrosoftExtensionsConfigurationAbstractionsPackageVersion>2.2.0-preview1-34823</MicrosoftExtensionsConfigurationAbstractionsPackageVersion>
<MicrosoftExtensionsConfigurationBinderPackageVersion>2.2.0-preview1-34823</MicrosoftExtensionsConfigurationBinderPackageVersion>
<MicrosoftExtensionsConfigurationCommandLinePackageVersion>2.2.0-preview1-34823</MicrosoftExtensionsConfigurationCommandLinePackageVersion>
<MicrosoftExtensionsConfigurationEnvironmentVariablesPackageVersion>2.2.0-preview1-34823</MicrosoftExtensionsConfigurationEnvironmentVariablesPackageVersion>
<MicrosoftExtensionsConfigurationFileExtensionsPackageVersion>2.2.0-preview1-34823</MicrosoftExtensionsConfigurationFileExtensionsPackageVersion>
<MicrosoftExtensionsConfigurationJsonPackageVersion>2.2.0-preview1-34823</MicrosoftExtensionsConfigurationJsonPackageVersion>
<MicrosoftExtensionsConfigurationPackageVersion>2.2.0-preview1-34823</MicrosoftExtensionsConfigurationPackageVersion>
<MicrosoftExtensionsDependencyInjectionAbstractionsPackageVersion>2.2.0-preview1-34823</MicrosoftExtensionsDependencyInjectionAbstractionsPackageVersion>
<MicrosoftExtensionsDependencyInjectionPackageVersion>2.2.0-preview1-34823</MicrosoftExtensionsDependencyInjectionPackageVersion>
<MicrosoftExtensionsDiagnosticAdapterPackageVersion>2.2.0-preview1-34823</MicrosoftExtensionsDiagnosticAdapterPackageVersion>
<MicrosoftExtensionsFileProvidersAbstractionsPackageVersion>2.2.0-preview1-34823</MicrosoftExtensionsFileProvidersAbstractionsPackageVersion>
<MicrosoftExtensionsFileProvidersEmbeddedPackageVersion>2.2.0-preview1-34823</MicrosoftExtensionsFileProvidersEmbeddedPackageVersion>
<MicrosoftExtensionsFileProvidersPhysicalPackageVersion>2.2.0-preview1-34823</MicrosoftExtensionsFileProvidersPhysicalPackageVersion>
<MicrosoftExtensionsLoggingAbstractionsPackageVersion>2.2.0-preview1-34823</MicrosoftExtensionsLoggingAbstractionsPackageVersion>
<MicrosoftExtensionsLoggingConsolePackageVersion>2.2.0-preview1-34823</MicrosoftExtensionsLoggingConsolePackageVersion>
<MicrosoftExtensionsLoggingPackageVersion>2.2.0-preview1-34823</MicrosoftExtensionsLoggingPackageVersion>
<MicrosoftExtensionsLoggingTestingPackageVersion>2.2.0-preview1-34823</MicrosoftExtensionsLoggingTestingPackageVersion>
<MicrosoftExtensionsOptionsPackageVersion>2.2.0-preview1-34823</MicrosoftExtensionsOptionsPackageVersion>
<MicrosoftExtensionsProcessSourcesPackageVersion>2.2.0-preview1-34823</MicrosoftExtensionsProcessSourcesPackageVersion>
<MicrosoftExtensionsRazorViewsSourcesPackageVersion>2.2.0-preview1-34823</MicrosoftExtensionsRazorViewsSourcesPackageVersion>
<MicrosoftExtensionsStackTraceSourcesPackageVersion>2.2.0-preview1-34823</MicrosoftExtensionsStackTraceSourcesPackageVersion>
<MicrosoftExtensionsTypeNameHelperSourcesPackageVersion>2.2.0-preview1-34823</MicrosoftExtensionsTypeNameHelperSourcesPackageVersion>
<MicrosoftAspNetCoreHttpAbstractionsPackageVersion>2.2.0-preview1-34825</MicrosoftAspNetCoreHttpAbstractionsPackageVersion>
<MicrosoftAspNetCoreHttpExtensionsPackageVersion>2.2.0-preview1-34825</MicrosoftAspNetCoreHttpExtensionsPackageVersion>
<MicrosoftAspNetCoreHttpFeaturesPackageVersion>2.2.0-preview1-34825</MicrosoftAspNetCoreHttpFeaturesPackageVersion>
<MicrosoftAspNetCoreHttpPackageVersion>2.2.0-preview1-34825</MicrosoftAspNetCoreHttpPackageVersion>
<MicrosoftAspNetCoreOwinPackageVersion>2.2.0-preview1-34825</MicrosoftAspNetCoreOwinPackageVersion>
<MicrosoftAspNetCoreTestingPackageVersion>2.2.0-preview1-34825</MicrosoftAspNetCoreTestingPackageVersion>
<MicrosoftExtensionsConfigurationAbstractionsPackageVersion>2.2.0-preview1-34825</MicrosoftExtensionsConfigurationAbstractionsPackageVersion>
<MicrosoftExtensionsConfigurationBinderPackageVersion>2.2.0-preview1-34825</MicrosoftExtensionsConfigurationBinderPackageVersion>
<MicrosoftExtensionsConfigurationCommandLinePackageVersion>2.2.0-preview1-34825</MicrosoftExtensionsConfigurationCommandLinePackageVersion>
<MicrosoftExtensionsConfigurationEnvironmentVariablesPackageVersion>2.2.0-preview1-34825</MicrosoftExtensionsConfigurationEnvironmentVariablesPackageVersion>
<MicrosoftExtensionsConfigurationFileExtensionsPackageVersion>2.2.0-preview1-34825</MicrosoftExtensionsConfigurationFileExtensionsPackageVersion>
<MicrosoftExtensionsConfigurationJsonPackageVersion>2.2.0-preview1-34825</MicrosoftExtensionsConfigurationJsonPackageVersion>
<MicrosoftExtensionsConfigurationPackageVersion>2.2.0-preview1-34825</MicrosoftExtensionsConfigurationPackageVersion>
<MicrosoftExtensionsDependencyInjectionAbstractionsPackageVersion>2.2.0-preview1-34825</MicrosoftExtensionsDependencyInjectionAbstractionsPackageVersion>
<MicrosoftExtensionsDependencyInjectionPackageVersion>2.2.0-preview1-34825</MicrosoftExtensionsDependencyInjectionPackageVersion>
<MicrosoftExtensionsDiagnosticAdapterPackageVersion>2.2.0-preview1-34825</MicrosoftExtensionsDiagnosticAdapterPackageVersion>
<MicrosoftExtensionsFileProvidersAbstractionsPackageVersion>2.2.0-preview1-34825</MicrosoftExtensionsFileProvidersAbstractionsPackageVersion>
<MicrosoftExtensionsFileProvidersEmbeddedPackageVersion>2.2.0-preview1-34825</MicrosoftExtensionsFileProvidersEmbeddedPackageVersion>
<MicrosoftExtensionsFileProvidersPhysicalPackageVersion>2.2.0-preview1-34825</MicrosoftExtensionsFileProvidersPhysicalPackageVersion>
<MicrosoftExtensionsLoggingAbstractionsPackageVersion>2.2.0-preview1-34825</MicrosoftExtensionsLoggingAbstractionsPackageVersion>
<MicrosoftExtensionsLoggingConsolePackageVersion>2.2.0-preview1-34825</MicrosoftExtensionsLoggingConsolePackageVersion>
<MicrosoftExtensionsLoggingPackageVersion>2.2.0-preview1-34825</MicrosoftExtensionsLoggingPackageVersion>
<MicrosoftExtensionsLoggingTestingPackageVersion>2.2.0-preview1-34825</MicrosoftExtensionsLoggingTestingPackageVersion>
<MicrosoftExtensionsOptionsPackageVersion>2.2.0-preview1-34825</MicrosoftExtensionsOptionsPackageVersion>
<MicrosoftExtensionsProcessSourcesPackageVersion>2.2.0-preview1-34825</MicrosoftExtensionsProcessSourcesPackageVersion>
<MicrosoftExtensionsRazorViewsSourcesPackageVersion>2.2.0-preview1-34825</MicrosoftExtensionsRazorViewsSourcesPackageVersion>
<MicrosoftExtensionsStackTraceSourcesPackageVersion>2.2.0-preview1-34825</MicrosoftExtensionsStackTraceSourcesPackageVersion>
<MicrosoftExtensionsTypeNameHelperSourcesPackageVersion>2.2.0-preview1-34825</MicrosoftExtensionsTypeNameHelperSourcesPackageVersion>
<MicrosoftNETCoreApp20PackageVersion>2.0.9</MicrosoftNETCoreApp20PackageVersion>
<MicrosoftNETCoreApp21PackageVersion>2.1.2</MicrosoftNETCoreApp21PackageVersion>
<MicrosoftNETCoreApp22PackageVersion>2.2.0-preview1-26618-02</MicrosoftNETCoreApp22PackageVersion>

Просмотреть файл

@ -0,0 +1,127 @@
// 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.Diagnostics;
using System.IO;
using System.Runtime.InteropServices;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
namespace Microsoft.AspNetCore.Server.IntegrationTesting
{
public class ApplicationPublisher
{
public string ApplicationPath { get; }
public ApplicationPublisher(string applicationPath)
{
ApplicationPath = applicationPath;
}
public static readonly string DotnetCommandName = "dotnet";
public virtual Task<PublishedApplication> Publish(DeploymentParameters deploymentParameters, ILogger logger)
{
var publishDirectory = CreateTempDirectory();
using (logger.BeginScope("dotnet-publish"))
{
if (string.IsNullOrEmpty(deploymentParameters.TargetFramework))
{
throw new Exception($"A target framework must be specified in the deployment parameters for applications that require publishing before deployment");
}
var parameters = $"publish "
+ $" --output \"{publishDirectory.FullName}\""
+ $" --framework {deploymentParameters.TargetFramework}"
+ $" --configuration {deploymentParameters.Configuration}"
+ (deploymentParameters.RestoreOnPublish
? string.Empty
: " --no-restore -p:VerifyMatchingImplicitPackageVersion=false");
// Set VerifyMatchingImplicitPackageVersion to disable errors when Microsoft.NETCore.App's version is overridden externally
// This verification doesn't matter if we are skipping restore during tests.
if (deploymentParameters.ApplicationType == ApplicationType.Standalone)
{
parameters += $" --runtime {GetRuntimeIdentifier(deploymentParameters)}";
}
parameters += $" {deploymentParameters.AdditionalPublishParameters}";
var startInfo = new ProcessStartInfo
{
FileName = DotnetCommandName,
Arguments = parameters,
UseShellExecute = false,
CreateNoWindow = true,
RedirectStandardError = true,
RedirectStandardOutput = true,
WorkingDirectory = deploymentParameters.ApplicationPath,
};
ProcessHelpers.AddEnvironmentVariablesToProcess(startInfo, deploymentParameters.PublishEnvironmentVariables, logger);
var hostProcess = new Process() { StartInfo = startInfo };
logger.LogInformation($"Executing command {DotnetCommandName} {parameters}");
hostProcess.StartAndCaptureOutAndErrToLogger("dotnet-publish", logger);
// A timeout is passed to Process.WaitForExit() for two reasons:
//
// 1. When process output is read asynchronously, WaitForExit() without a timeout blocks until child processes
// are killed, which can cause hangs due to MSBuild NodeReuse child processes started by dotnet.exe.
// With a timeout, WaitForExit() returns when the parent process is killed and ignores child processes.
// https://stackoverflow.com/a/37983587/102052
//
// 2. If "dotnet publish" does hang indefinitely for some reason, tests should fail fast with an error message.
const int timeoutMinutes = 5;
if (hostProcess.WaitForExit(milliseconds: timeoutMinutes * 60 * 1000))
{
if (hostProcess.ExitCode != 0)
{
var message = $"{DotnetCommandName} publish exited with exit code : {hostProcess.ExitCode}";
logger.LogError(message);
throw new Exception(message);
}
}
else
{
var message = $"{DotnetCommandName} publish failed to exit after {timeoutMinutes} minutes";
logger.LogError(message);
throw new Exception(message);
}
logger.LogInformation($"{DotnetCommandName} publish finished with exit code : {hostProcess.ExitCode}");
}
return Task.FromResult(new PublishedApplication(publishDirectory.FullName, logger));
}
private static string GetRuntimeIdentifier(DeploymentParameters deploymentParameters)
{
var architecture = deploymentParameters.RuntimeArchitecture;
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
return "win7-" + architecture;
}
if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
{
return "linux-" + architecture;
}
if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
{
return "osx-" + architecture;
}
throw new InvalidOperationException("Unrecognized operation system platform");
}
protected static DirectoryInfo CreateTempDirectory()
{
var tempPath = Path.GetTempPath() + Guid.NewGuid().ToString("N");
var target = new DirectoryInfo(tempPath);
target.Create();
return target;
}
}
}

Просмотреть файл

@ -0,0 +1,101 @@
// 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.IO;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
namespace Microsoft.AspNetCore.Server.IntegrationTesting
{
public class CachingApplicationPublisher: ApplicationPublisher, IDisposable
{
private readonly Dictionary<DotnetPublishParameters, PublishedApplication> _publishCache = new Dictionary<DotnetPublishParameters, PublishedApplication>();
public CachingApplicationPublisher(string applicationPath) : base(applicationPath)
{
}
public override async Task<PublishedApplication> Publish(DeploymentParameters deploymentParameters, ILogger logger)
{
if (ApplicationPath != deploymentParameters.ApplicationPath)
{
throw new InvalidOperationException("ApplicationPath mismatch");
}
if (deploymentParameters.PublishEnvironmentVariables.Any())
{
throw new InvalidOperationException("DeploymentParameters.PublishEnvironmentVariables not supported");
}
if (!string.IsNullOrEmpty(deploymentParameters.PublishedApplicationRootPath))
{
throw new InvalidOperationException("DeploymentParameters.PublishedApplicationRootPath not supported");
}
if (deploymentParameters.RestoreOnPublish)
{
throw new InvalidOperationException("DeploymentParameters.RestoreOnPublish not supported");
}
var dotnetPublishParameters = new DotnetPublishParameters
{
TargetFramework = deploymentParameters.TargetFramework,
Configuration = deploymentParameters.Configuration,
ApplicationType = deploymentParameters.ApplicationType,
RuntimeArchitecture = deploymentParameters.RuntimeArchitecture
};
if (!_publishCache.TryGetValue(dotnetPublishParameters, out var publishedApplication))
{
publishedApplication = await base.Publish(deploymentParameters, logger);
_publishCache.Add(dotnetPublishParameters, publishedApplication);
}
return new PublishedApplication(CopyPublishedOutput(publishedApplication, logger), logger);
}
private string CopyPublishedOutput(PublishedApplication application, ILogger logger)
{
var target = CreateTempDirectory();
var source = new DirectoryInfo(application.Path);
CopyFiles(source, target, logger);
return target.FullName;
}
public static void CopyFiles(DirectoryInfo source, DirectoryInfo target, ILogger logger)
{
foreach (DirectoryInfo directoryInfo in source.GetDirectories())
{
CopyFiles(directoryInfo, target.CreateSubdirectory(directoryInfo.Name), logger);
}
logger.LogDebug($"Processing {target.FullName}");
foreach (FileInfo fileInfo in source.GetFiles())
{
logger.LogDebug($" Copying {fileInfo.Name}");
var destFileName = Path.Combine(target.FullName, fileInfo.Name);
fileInfo.CopyTo(destFileName);
}
}
public void Dispose()
{
foreach (var publishedApp in _publishCache.Values)
{
publishedApp.Dispose();
}
}
private struct DotnetPublishParameters
{
public string TargetFramework { get; set; }
public string Configuration { get; set; }
public ApplicationType ApplicationType { get; set; }
public RuntimeArchitecture RuntimeArchitecture { get; set; }
}
}
}

Просмотреть файл

@ -99,6 +99,8 @@ namespace Microsoft.AspNetCore.Server.IntegrationTesting
}
}
public ApplicationPublisher ApplicationPublisher { get; set; }
public ServerType ServerType { get; set; }
public RuntimeFlavor RuntimeFlavor { get; set; }

Просмотреть файл

@ -20,12 +20,10 @@ namespace Microsoft.AspNetCore.Server.IntegrationTesting
{
public static readonly string DotnetCommandName = "dotnet";
// This is the argument that separates the dotnet arguments for the args being passed to the
// app being run when running dotnet run
public static readonly string DotnetArgumentSeparator = "--";
private readonly Stopwatch _stopwatch = new Stopwatch();
private PublishedApplication _publishedApplication;
public ApplicationDeployer(DeploymentParameters deploymentParameters, ILoggerFactory loggerFactory)
{
DeploymentParameters = deploymentParameters;
@ -82,78 +80,9 @@ namespace Microsoft.AspNetCore.Server.IntegrationTesting
protected void DotnetPublish(string publishRoot = null)
{
using (Logger.BeginScope("dotnet-publish"))
{
if (string.IsNullOrEmpty(DeploymentParameters.TargetFramework))
{
throw new Exception($"A target framework must be specified in the deployment parameters for applications that require publishing before deployment");
}
DeploymentParameters.PublishedApplicationRootPath = publishRoot ?? Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());
var parameters = $"publish "
+ $" --output \"{DeploymentParameters.PublishedApplicationRootPath}\""
+ $" --framework {DeploymentParameters.TargetFramework}"
+ $" --configuration {DeploymentParameters.Configuration}"
+ (DeploymentParameters.RestoreOnPublish
? string.Empty
: " --no-restore -p:VerifyMatchingImplicitPackageVersion=false");
// Set VerifyMatchingImplicitPackageVersion to disable errors when Microsoft.NETCore.App's version is overridden externally
// This verification doesn't matter if we are skipping restore during tests.
if (DeploymentParameters.ApplicationType == ApplicationType.Standalone)
{
parameters += $" --runtime {GetRuntimeIdentifier()}";
}
parameters += $" {DeploymentParameters.AdditionalPublishParameters}";
var startInfo = new ProcessStartInfo
{
FileName = DotnetCommandName,
Arguments = parameters,
UseShellExecute = false,
CreateNoWindow = true,
RedirectStandardError = true,
RedirectStandardOutput = true,
WorkingDirectory = DeploymentParameters.ApplicationPath,
};
AddEnvironmentVariablesToProcess(startInfo, DeploymentParameters.PublishEnvironmentVariables);
var hostProcess = new Process() { StartInfo = startInfo };
Logger.LogInformation($"Executing command {DotnetCommandName} {parameters}");
hostProcess.StartAndCaptureOutAndErrToLogger("dotnet-publish", Logger);
// A timeout is passed to Process.WaitForExit() for two reasons:
//
// 1. When process output is read asynchronously, WaitForExit() without a timeout blocks until child processes
// are killed, which can cause hangs due to MSBuild NodeReuse child processes started by dotnet.exe.
// With a timeout, WaitForExit() returns when the parent process is killed and ignores child processes.
// https://stackoverflow.com/a/37983587/102052
//
// 2. If "dotnet publish" does hang indefinitely for some reason, tests should fail fast with an error message.
const int timeoutMinutes = 5;
if (hostProcess.WaitForExit(milliseconds: timeoutMinutes * 60 * 1000))
{
if (hostProcess.ExitCode != 0)
{
var message = $"{DotnetCommandName} publish exited with exit code : {hostProcess.ExitCode}";
Logger.LogError(message);
throw new Exception(message);
}
}
else
{
var message = $"{DotnetCommandName} publish failed to exit after {timeoutMinutes} minutes";
Logger.LogError(message);
throw new Exception(message);
}
Logger.LogInformation($"{DotnetCommandName} publish finished with exit code : {hostProcess.ExitCode}");
}
var publisher = DeploymentParameters.ApplicationPublisher ?? new ApplicationPublisher(DeploymentParameters.ApplicationPath);
_publishedApplication = publisher.Publish(DeploymentParameters, Logger).GetAwaiter().GetResult();
DeploymentParameters.PublishedApplicationRootPath = _publishedApplication.Path;
}
protected void CleanPublishedOutput()
@ -168,11 +97,7 @@ namespace Microsoft.AspNetCore.Server.IntegrationTesting
}
else
{
RetryHelper.RetryOperation(
() => Directory.Delete(DeploymentParameters.PublishedApplicationRootPath, true),
e => Logger.LogWarning($"Failed to delete directory : {e.Message}"),
retryCount: 3,
retryDelayMilliseconds: 100);
_publishedApplication.Dispose();
}
}
}
@ -219,26 +144,8 @@ namespace Microsoft.AspNetCore.Server.IntegrationTesting
protected void AddEnvironmentVariablesToProcess(ProcessStartInfo startInfo, IDictionary<string, string> environmentVariables)
{
var environment = startInfo.Environment;
SetEnvironmentVariable(environment, "ASPNETCORE_ENVIRONMENT", DeploymentParameters.EnvironmentName);
foreach (var environmentVariable in environmentVariables)
{
SetEnvironmentVariable(environment, environmentVariable.Key, environmentVariable.Value);
}
}
protected void SetEnvironmentVariable(IDictionary<string, string> environment, string name, string value)
{
if (value == null)
{
Logger.LogInformation("Removing environment variable {name}", name);
environment.Remove(name);
}
else
{
Logger.LogInformation("SET {name}={value}", name, value);
environment[name] = value;
}
ProcessHelpers.SetEnvironmentVariable(environment, "ASPNETCORE_ENVIRONMENT", DeploymentParameters.EnvironmentName, Logger);
ProcessHelpers.AddEnvironmentVariablesToProcess(startInfo, environmentVariables, Logger);
}
protected void InvokeUserApplicationCleanup()
@ -286,26 +193,5 @@ namespace Microsoft.AspNetCore.Server.IntegrationTesting
}
public abstract void Dispose();
private string GetRuntimeIdentifier()
{
var architecture = DeploymentParameters.RuntimeArchitecture;
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
return "win7-" + architecture;
}
else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
{
return "linux-" + architecture;
}
else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
{
return "osx-" + architecture;
}
else
{
throw new InvalidOperationException("Unrecognized operation system platform");
}
}
}
}

Просмотреть файл

@ -0,0 +1,36 @@
// 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.Collections.Generic;
using System.Diagnostics;
using Microsoft.Extensions.Logging;
namespace Microsoft.AspNetCore.Server.IntegrationTesting
{
internal class ProcessHelpers
{
public static void AddEnvironmentVariablesToProcess(ProcessStartInfo startInfo, IDictionary<string, string> environmentVariables, ILogger logger)
{
var environment = startInfo.Environment;
foreach (var environmentVariable in environmentVariables)
{
SetEnvironmentVariable(environment, environmentVariable.Key, environmentVariable.Value, logger);
}
}
public static void SetEnvironmentVariable(IDictionary<string, string> environment, string name, string value, ILogger logger)
{
if (value == null)
{
logger.LogInformation("Removing environment variable {name}", name);
environment.Remove(name);
}
else
{
logger.LogInformation("SET {name}={value}", name, value);
environment[name] = value;
}
}
}
}

Просмотреть файл

@ -0,0 +1,31 @@
// 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.IO;
using Microsoft.Extensions.Logging;
namespace Microsoft.AspNetCore.Server.IntegrationTesting
{
public class PublishedApplication: IDisposable
{
private readonly ILogger _logger;
public string Path { get; }
public PublishedApplication(string path, ILogger logger)
{
_logger = logger;
Path = path;
}
public void Dispose()
{
RetryHelper.RetryOperation(
() => Directory.Delete(Path, true),
e => _logger.LogWarning($"Failed to delete directory : {e.Message}"),
retryCount: 3,
retryDelayMilliseconds: 100);
}
}
}