From 1ae1ff01a3573832d111c83ac2cc185d03087c1b Mon Sep 17 00:00:00 2001 From: Andrew Stanton-Nurse Date: Thu, 6 Apr 2017 15:19:26 -0700 Subject: [PATCH] Add test logging helpers to Hosting (#1005) --- build/dependencies.props | 4 +- .../Common/DeploymentResult.cs | 43 ++++- .../Common/LoggingHandler.cs | 34 ++++ .../Common/ProcessLoggingExtensions.cs | 2 +- .../Common/RetryHelper.cs | 4 +- .../Deployers/ApplicationDeployer.cs | 6 +- .../Deployers/ApplicationDeployerFactory.cs | 6 +- .../Deployers/IISExpressDeployer.cs | 19 +- .../Deployers/NginxDeployer.cs | 17 +- .../RemoteWindowsDeployer.cs | 13 +- .../Deployers/SelfHostDeployer.cs | 17 +- ...spNetCore.Server.IntegrationTesting.csproj | 10 +- .../xunit/TestLogging.cs | 166 ++++++++++++++++++ .../ShutdownTests.cs | 74 ++++---- 14 files changed, 329 insertions(+), 86 deletions(-) create mode 100644 src/Microsoft.AspNetCore.Server.IntegrationTesting/Common/LoggingHandler.cs create mode 100644 src/Microsoft.AspNetCore.Server.IntegrationTesting/xunit/TestLogging.cs diff --git a/build/dependencies.props b/build/dependencies.props index 55e145f789..db8feeeac0 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -11,5 +11,7 @@ 7.0.0 1.0.1 2.2.0 + 1.4.0 + 3.2.0 - \ No newline at end of file + diff --git a/src/Microsoft.AspNetCore.Server.IntegrationTesting/Common/DeploymentResult.cs b/src/Microsoft.AspNetCore.Server.IntegrationTesting/Common/DeploymentResult.cs index 4ea3a0518d..6aed1f4d64 100644 --- a/src/Microsoft.AspNetCore.Server.IntegrationTesting/Common/DeploymentResult.cs +++ b/src/Microsoft.AspNetCore.Server.IntegrationTesting/Common/DeploymentResult.cs @@ -1,7 +1,10 @@ // 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.Http; using System.Threading; +using Microsoft.Extensions.Logging; namespace Microsoft.AspNetCore.Server.IntegrationTesting { @@ -10,25 +13,57 @@ namespace Microsoft.AspNetCore.Server.IntegrationTesting /// public class DeploymentResult { + private readonly ILoggerFactory _loggerFactory; + /// /// Base Uri of the deployment application. /// - public string ApplicationBaseUri { get; set; } + public string ApplicationBaseUri { get; } /// /// The folder where the application is hosted. This path can be different from the /// original application source location if published before deployment. /// - public string ContentRoot { get; set; } + public string ContentRoot { get; } /// /// Original deployment parameters used for this deployment. /// - public DeploymentParameters DeploymentParameters { get; set; } + public DeploymentParameters DeploymentParameters { get; } /// /// Triggered when the host process dies or pulled down. /// - public CancellationToken HostShutdownToken { get; set; } + public CancellationToken HostShutdownToken { get; } + + /// + /// An with configured and the set to the + /// + public HttpClient HttpClient { get; } + + public DeploymentResult(ILoggerFactory loggerFactory, DeploymentParameters deploymentParameters, string applicationBaseUri) + : this(loggerFactory, deploymentParameters: deploymentParameters, applicationBaseUri: applicationBaseUri, contentRoot: string.Empty, hostShutdownToken: CancellationToken.None) + { } + + public DeploymentResult(ILoggerFactory loggerFactory, DeploymentParameters deploymentParameters, string applicationBaseUri, string contentRoot, CancellationToken hostShutdownToken) + { + _loggerFactory = loggerFactory; + + ApplicationBaseUri = applicationBaseUri; + ContentRoot = contentRoot; + DeploymentParameters = deploymentParameters; + HostShutdownToken = hostShutdownToken; + + HttpClient = CreateHttpClient(new HttpClientHandler()); + } + + /// + /// Create an with configured and the set to the , + /// but using the provided and the underlying handler. + /// + /// + /// + public HttpClient CreateHttpClient(HttpMessageHandler baseHandler) => + new HttpClient(new LoggingHandler(_loggerFactory, baseHandler)) { BaseAddress = new Uri(ApplicationBaseUri) }; } } \ No newline at end of file diff --git a/src/Microsoft.AspNetCore.Server.IntegrationTesting/Common/LoggingHandler.cs b/src/Microsoft.AspNetCore.Server.IntegrationTesting/Common/LoggingHandler.cs new file mode 100644 index 0000000000..31d52aed07 --- /dev/null +++ b/src/Microsoft.AspNetCore.Server.IntegrationTesting/Common/LoggingHandler.cs @@ -0,0 +1,34 @@ +using System; +using System.Net.Http; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.Extensions.Logging; + +namespace Microsoft.AspNetCore.Server.IntegrationTesting +{ + internal class LoggingHandler : DelegatingHandler + { + private ILogger _logger; + + public LoggingHandler(ILoggerFactory loggerFactory, HttpMessageHandler innerHandler) : base(innerHandler) + { + _logger = loggerFactory.CreateLogger(); + } + + protected override async Task SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) + { + _logger.LogDebug("Sending {method} {url}", request.Method, request.RequestUri); + try + { + var response = await base.SendAsync(request, cancellationToken); + _logger.LogDebug("Received {statusCode} {reasonPhrase} {url}", response.StatusCode, response.ReasonPhrase, request.RequestUri); + return response; + } + catch (Exception ex) + { + _logger.LogError(0, ex, "Exception while sending '{method} {url}'", request.Method, request.RequestUri, request.RequestUri); + throw; + } + } + } +} \ No newline at end of file diff --git a/src/Microsoft.AspNetCore.Server.IntegrationTesting/Common/ProcessLoggingExtensions.cs b/src/Microsoft.AspNetCore.Server.IntegrationTesting/Common/ProcessLoggingExtensions.cs index d85b255a47..8d7d20bc1e 100644 --- a/src/Microsoft.AspNetCore.Server.IntegrationTesting/Common/ProcessLoggingExtensions.cs +++ b/src/Microsoft.AspNetCore.Server.IntegrationTesting/Common/ProcessLoggingExtensions.cs @@ -14,7 +14,7 @@ namespace System.Diagnostics { if (!string.IsNullOrEmpty(dataArgs.Data)) { - logger.LogWarning($"{prefix} stdout: {{line}}", dataArgs.Data); + logger.LogInformation($"{prefix} stdout: {{line}}", dataArgs.Data); } }; diff --git a/src/Microsoft.AspNetCore.Server.IntegrationTesting/Common/RetryHelper.cs b/src/Microsoft.AspNetCore.Server.IntegrationTesting/Common/RetryHelper.cs index c8262eb989..46f84ee494 100644 --- a/src/Microsoft.AspNetCore.Server.IntegrationTesting/Common/RetryHelper.cs +++ b/src/Microsoft.AspNetCore.Server.IntegrationTesting/Common/RetryHelper.cs @@ -1,4 +1,4 @@ -// Copyright (c) .NET Foundation. All rights reserved. +// 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; @@ -59,7 +59,7 @@ namespace Microsoft.AspNetCore.Server.IntegrationTesting if (exception is HttpRequestException #if NET46 || exception is System.Net.WebException -#elif NETSTANDARD1_3 +#elif NETSTANDARD1_5 #else #error Target frameworks need to be updated. #endif diff --git a/src/Microsoft.AspNetCore.Server.IntegrationTesting/Deployers/ApplicationDeployer.cs b/src/Microsoft.AspNetCore.Server.IntegrationTesting/Deployers/ApplicationDeployer.cs index 542d904795..233fbd94ca 100644 --- a/src/Microsoft.AspNetCore.Server.IntegrationTesting/Deployers/ApplicationDeployer.cs +++ b/src/Microsoft.AspNetCore.Server.IntegrationTesting/Deployers/ApplicationDeployer.cs @@ -26,14 +26,16 @@ namespace Microsoft.AspNetCore.Server.IntegrationTesting private readonly Stopwatch _stopwatch = new Stopwatch(); - public ApplicationDeployer(DeploymentParameters deploymentParameters, ILogger logger) + public ApplicationDeployer(DeploymentParameters deploymentParameters, ILoggerFactory loggerFactory) { DeploymentParameters = deploymentParameters; - Logger = logger; + LoggerFactory = loggerFactory; + Logger = LoggerFactory.CreateLogger(GetType().FullName); } protected DeploymentParameters DeploymentParameters { get; } + protected ILoggerFactory LoggerFactory { get; } protected ILogger Logger { get; } public abstract Task DeployAsync(); diff --git a/src/Microsoft.AspNetCore.Server.IntegrationTesting/Deployers/ApplicationDeployerFactory.cs b/src/Microsoft.AspNetCore.Server.IntegrationTesting/Deployers/ApplicationDeployerFactory.cs index 31be63ea03..eb66761807 100644 --- a/src/Microsoft.AspNetCore.Server.IntegrationTesting/Deployers/ApplicationDeployerFactory.cs +++ b/src/Microsoft.AspNetCore.Server.IntegrationTesting/Deployers/ApplicationDeployerFactory.cs @@ -32,14 +32,14 @@ namespace Microsoft.AspNetCore.Server.IntegrationTesting switch (deploymentParameters.ServerType) { case ServerType.IISExpress: - return new IISExpressDeployer(deploymentParameters, loggerFactory.CreateLogger()); + return new IISExpressDeployer(deploymentParameters, loggerFactory); case ServerType.IIS: throw new NotSupportedException("The IIS deployer is no longer supported"); case ServerType.WebListener: case ServerType.Kestrel: - return new SelfHostDeployer(deploymentParameters, loggerFactory.CreateLogger()); + return new SelfHostDeployer(deploymentParameters, loggerFactory); case ServerType.Nginx: - return new NginxDeployer(deploymentParameters, loggerFactory.CreateLogger()); + return new NginxDeployer(deploymentParameters, loggerFactory); default: throw new NotSupportedException( string.Format("Found no deployers suitable for server type '{0}' with the current runtime.", diff --git a/src/Microsoft.AspNetCore.Server.IntegrationTesting/Deployers/IISExpressDeployer.cs b/src/Microsoft.AspNetCore.Server.IntegrationTesting/Deployers/IISExpressDeployer.cs index b1220198aa..6f0ad80e42 100644 --- a/src/Microsoft.AspNetCore.Server.IntegrationTesting/Deployers/IISExpressDeployer.cs +++ b/src/Microsoft.AspNetCore.Server.IntegrationTesting/Deployers/IISExpressDeployer.cs @@ -28,8 +28,8 @@ namespace Microsoft.AspNetCore.Server.IntegrationTesting private Process _hostProcess; - public IISExpressDeployer(DeploymentParameters deploymentParameters, ILogger logger) - : base(deploymentParameters, logger) + public IISExpressDeployer(DeploymentParameters deploymentParameters, ILoggerFactory loggerFactory) + : base(deploymentParameters, loggerFactory) { } @@ -75,14 +75,13 @@ namespace Microsoft.AspNetCore.Server.IntegrationTesting Logger.LogInformation("Application ready at URL: {appUrl}", actualUri); - return new DeploymentResult - { - ContentRoot = contentRoot, - DeploymentParameters = DeploymentParameters, - // Right now this works only for urls like http://localhost:5001/. Does not work for http://localhost:5001/subpath. - ApplicationBaseUri = actualUri.ToString(), - HostShutdownToken = hostExitToken - }; + // Right now this works only for urls like http://localhost:5001/. Does not work for http://localhost:5001/subpath. + return new DeploymentResult( + LoggerFactory, + DeploymentParameters, + applicationBaseUri: actualUri.ToString(), + contentRoot: contentRoot, + hostShutdownToken: hostExitToken); } } diff --git a/src/Microsoft.AspNetCore.Server.IntegrationTesting/Deployers/NginxDeployer.cs b/src/Microsoft.AspNetCore.Server.IntegrationTesting/Deployers/NginxDeployer.cs index 41d9860966..d7890419d1 100644 --- a/src/Microsoft.AspNetCore.Server.IntegrationTesting/Deployers/NginxDeployer.cs +++ b/src/Microsoft.AspNetCore.Server.IntegrationTesting/Deployers/NginxDeployer.cs @@ -19,8 +19,8 @@ namespace Microsoft.AspNetCore.Server.IntegrationTesting private string _configFile; private readonly int _waitTime = (int)TimeSpan.FromSeconds(30).TotalMilliseconds; - public NginxDeployer(DeploymentParameters deploymentParameters, ILogger logger) - : base(deploymentParameters, logger) + public NginxDeployer(DeploymentParameters deploymentParameters, ILoggerFactory loggerFactory) + : base(deploymentParameters, loggerFactory) { } @@ -61,13 +61,12 @@ namespace Microsoft.AspNetCore.Server.IntegrationTesting } } - return new DeploymentResult - { - ContentRoot = DeploymentParameters.ApplicationPath, - DeploymentParameters = DeploymentParameters, - ApplicationBaseUri = uri.ToString(), - HostShutdownToken = exitToken - }; + return new DeploymentResult( + LoggerFactory, + DeploymentParameters, + applicationBaseUri: uri.ToString(), + contentRoot: DeploymentParameters.ApplicationPath, + hostShutdownToken: exitToken); } } diff --git a/src/Microsoft.AspNetCore.Server.IntegrationTesting/Deployers/RemoteWindowsDeployer/RemoteWindowsDeployer.cs b/src/Microsoft.AspNetCore.Server.IntegrationTesting/Deployers/RemoteWindowsDeployer/RemoteWindowsDeployer.cs index 02aef7116a..a102cd02da 100644 --- a/src/Microsoft.AspNetCore.Server.IntegrationTesting/Deployers/RemoteWindowsDeployer/RemoteWindowsDeployer.cs +++ b/src/Microsoft.AspNetCore.Server.IntegrationTesting/Deployers/RemoteWindowsDeployer/RemoteWindowsDeployer.cs @@ -26,8 +26,8 @@ namespace Microsoft.AspNetCore.Server.IntegrationTesting private bool _isDisposed; private static readonly Lazy _scripts = new Lazy(() => CopyEmbeddedScriptFilesToDisk()); - public RemoteWindowsDeployer(RemoteWindowsDeploymentParameters deploymentParameters, ILogger logger) - : base(deploymentParameters, logger) + public RemoteWindowsDeployer(RemoteWindowsDeploymentParameters deploymentParameters, ILoggerFactory loggerFactory) + : base(deploymentParameters, loggerFactory) { _deploymentParameters = deploymentParameters; @@ -103,11 +103,10 @@ namespace Microsoft.AspNetCore.Server.IntegrationTesting await RunScriptAsync("StartServer"); - return new DeploymentResult - { - ApplicationBaseUri = DeploymentParameters.ApplicationBaseUriHint, - DeploymentParameters = DeploymentParameters - }; + return new DeploymentResult( + LoggerFactory, + DeploymentParameters, + DeploymentParameters.ApplicationBaseUriHint); } } diff --git a/src/Microsoft.AspNetCore.Server.IntegrationTesting/Deployers/SelfHostDeployer.cs b/src/Microsoft.AspNetCore.Server.IntegrationTesting/Deployers/SelfHostDeployer.cs index 34e9b5cdb3..8c559181aa 100644 --- a/src/Microsoft.AspNetCore.Server.IntegrationTesting/Deployers/SelfHostDeployer.cs +++ b/src/Microsoft.AspNetCore.Server.IntegrationTesting/Deployers/SelfHostDeployer.cs @@ -24,8 +24,8 @@ namespace Microsoft.AspNetCore.Server.IntegrationTesting public Process HostProcess { get; private set; } - public SelfHostDeployer(DeploymentParameters deploymentParameters, ILogger logger) - : base(deploymentParameters, logger) + public SelfHostDeployer(DeploymentParameters deploymentParameters, ILoggerFactory loggerFactory) + : base(deploymentParameters, loggerFactory) { } @@ -48,13 +48,12 @@ namespace Microsoft.AspNetCore.Server.IntegrationTesting Logger.LogInformation("Application ready at URL: {appUrl}", actualUrl); - return new DeploymentResult - { - ContentRoot = DeploymentParameters.PublishApplicationBeforeDeployment ? DeploymentParameters.PublishedApplicationRootPath : DeploymentParameters.ApplicationPath, - DeploymentParameters = DeploymentParameters, - ApplicationBaseUri = actualUrl.ToString(), - HostShutdownToken = hostExitToken - }; + return new DeploymentResult( + LoggerFactory, + DeploymentParameters, + applicationBaseUri: actualUrl.ToString(), + contentRoot: DeploymentParameters.PublishApplicationBeforeDeployment ? DeploymentParameters.PublishedApplicationRootPath : DeploymentParameters.ApplicationPath, + hostShutdownToken: hostExitToken); } } diff --git a/src/Microsoft.AspNetCore.Server.IntegrationTesting/Microsoft.AspNetCore.Server.IntegrationTesting.csproj b/src/Microsoft.AspNetCore.Server.IntegrationTesting/Microsoft.AspNetCore.Server.IntegrationTesting.csproj index 8d2504447e..2d88c56830 100644 --- a/src/Microsoft.AspNetCore.Server.IntegrationTesting/Microsoft.AspNetCore.Server.IntegrationTesting.csproj +++ b/src/Microsoft.AspNetCore.Server.IntegrationTesting/Microsoft.AspNetCore.Server.IntegrationTesting.csproj @@ -5,7 +5,7 @@ ASP.NET Core helpers to deploy applications to IIS Express, IIS, WebListener and Kestrel for testing. 0.4.0 - net46;netstandard1.3 + net46;netstandard1.5 $(NoWarn);CS1591 true aspnetcore;testing @@ -20,11 +20,15 @@ - + + + + + @@ -33,7 +37,7 @@ - + diff --git a/src/Microsoft.AspNetCore.Server.IntegrationTesting/xunit/TestLogging.cs b/src/Microsoft.AspNetCore.Server.IntegrationTesting/xunit/TestLogging.cs new file mode 100644 index 0000000000..11ad91baf9 --- /dev/null +++ b/src/Microsoft.AspNetCore.Server.IntegrationTesting/xunit/TestLogging.cs @@ -0,0 +1,166 @@ +// 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.Reflection; +using System.Runtime.CompilerServices; +using Microsoft.Extensions.Logging; +using Serilog; +using Xunit.Abstractions; + +namespace Microsoft.AspNetCore.Server.IntegrationTesting.xunit +{ + public static class TestLogging + { + // Need to qualify because of Serilog.ILogger :( + private static readonly object _initLock = new object(); + private volatile static Extensions.Logging.ILogger GlobalLogger = null; + + public static readonly string OutputDirectoryEnvironmentVariableName = "ASPNETCORE_TEST_LOG_DIR"; + public static readonly string TestOutputRoot; + + static TestLogging() + { + TestOutputRoot = Environment.GetEnvironmentVariable(OutputDirectoryEnvironmentVariableName); + } + + public static IDisposable Start(ITestOutputHelper output, out ILoggerFactory loggerFactory, [CallerMemberName] string testName = null) => + Start(output, out loggerFactory, typeof(TTestClass).GetTypeInfo().Assembly.GetName().Name, typeof(TTestClass).FullName, testName); + + public static IDisposable Start(ITestOutputHelper output, out ILoggerFactory loggerFactory, string appName, string className, [CallerMemberName] string testName = null) + { + EnsureGlobalLoggingInitialized(appName); + + var factory = CreateLoggerFactory(output, appName, className, testName); + loggerFactory = factory; + var logger = factory.CreateLogger("TestLifetime"); + + var stopwatch = Stopwatch.StartNew(); + GlobalLogger.LogInformation("Starting test {testName}", testName); + logger.LogInformation("Starting test {testName}", testName); + + return new Disposable(() => + { + stopwatch.Stop(); + GlobalLogger.LogInformation("Finished test {testName} in {duration}s", testName, stopwatch.Elapsed.TotalSeconds); + logger.LogInformation("Finished test {testName} in {duration}s", testName, stopwatch.Elapsed.TotalSeconds); + factory.Dispose(); + }); + } + + public static ILoggerFactory CreateLoggerFactory(ITestOutputHelper output, [CallerMemberName] string testName = null) => + CreateLoggerFactory(output, typeof(TTestClass).GetTypeInfo().Assembly.GetName().Name, typeof(TTestClass).FullName, testName); + + public static ILoggerFactory CreateLoggerFactory(ITestOutputHelper output, string appName, string className, [CallerMemberName] string testName = null) + { + var loggerFactory = new LoggerFactory(); + loggerFactory.AddXunit(output, LogLevel.Debug); + + // Try to shorten the class name using the assembly name + if (className.StartsWith(appName + ".")) + { + className = className.Substring(appName.Length + 1); + } + + var testOutputFile = Path.Combine(appName, className, $"{testName}.log"); + AddFileLogging(loggerFactory, testOutputFile); + + return loggerFactory; + } + + // Need to qualify because of Serilog.ILogger :( + private static Extensions.Logging.ILogger CreateGlobalLogger(string assemblyName) + { + var loggerFactory = new LoggerFactory(); + + // Let the global logger log to the console, it's just "Starting X..." "Finished X..." + loggerFactory.AddConsole(); + + var globalLogFileName = Path.Combine(assemblyName, "global.log"); + AddFileLogging(loggerFactory, globalLogFileName); + + var logger = loggerFactory.CreateLogger("GlobalTestLog"); + logger.LogInformation($"Global Test Logging initialized. Set the '{OutputDirectoryEnvironmentVariableName}' Environment Variable in order to create log files on disk."); + return logger; + } + + private static void AddFileLogging(ILoggerFactory loggerFactory, string fileName) + { + if (!string.IsNullOrEmpty(TestOutputRoot)) + { + fileName = Path.Combine(TestOutputRoot, fileName); + + var dir = Path.GetDirectoryName(fileName); + if (!Directory.Exists(dir)) + { + Directory.CreateDirectory(dir); + } + + if (File.Exists(fileName)) + { + File.Delete(fileName); + } + + var serilogger = new LoggerConfiguration() + .Enrich.FromLogContext() + .MinimumLevel.Verbose() + .WriteTo.File(fileName, flushToDiskInterval: TimeSpan.FromSeconds(1)) + .CreateLogger(); + loggerFactory.AddSerilog(serilogger); + } + } + + private static void EnsureGlobalLoggingInitialized(string assemblyName) + { + // Ye olde double-check lock because we need to pass the assembly name in if we are initializing + // so we can't use Lazy + if(GlobalLogger == null) + { + lock(_initLock) + { + if(GlobalLogger == null) + { + GlobalLogger = CreateGlobalLogger(assemblyName); + } + } + } + } + + private class Disposable : IDisposable + { + private Action _action; + + public Disposable(Action action) + { + _action = action; + } + + public void Dispose() + { + _action(); + } + } + } + + public abstract class LoggedTest + { + private readonly ITestOutputHelper _output; + + protected LoggedTest(ITestOutputHelper output) + { + _output = output; + } + + public IDisposable StartLog(out ILoggerFactory loggerFactory, [CallerMemberName] string testName = null) + { + return TestLogging.Start( + _output, + out loggerFactory, + GetType().GetTypeInfo().Assembly.GetName().Name, + GetType().FullName, + testName); + } + } +} diff --git a/test/Microsoft.AspNetCore.Hosting.FunctionalTests/ShutdownTests.cs b/test/Microsoft.AspNetCore.Hosting.FunctionalTests/ShutdownTests.cs index abf1cbb426..be1d602577 100644 --- a/test/Microsoft.AspNetCore.Hosting.FunctionalTests/ShutdownTests.cs +++ b/test/Microsoft.AspNetCore.Hosting.FunctionalTests/ShutdownTests.cs @@ -7,59 +7,63 @@ using System.Threading.Tasks; using Microsoft.AspNetCore.Server.IntegrationTesting; using Microsoft.AspNetCore.Server.IntegrationTesting.xunit; using Microsoft.AspNetCore.Testing.xunit; -using Microsoft.Extensions.Logging; using Xunit; +using Xunit.Abstractions; namespace Microsoft.AspNetCore.Hosting.FunctionalTests { - public class ShutdownTests + public class ShutdownTests : LoggedTest { + public ShutdownTests(ITestOutputHelper output) : base(output) + { + } + [ConditionalFact] [OSSkipCondition(OperatingSystems.Windows)] [OSSkipCondition(OperatingSystems.MacOSX)] public async Task ShutdownTest() { - var logger = new LoggerFactory() - .AddConsole() - .CreateLogger(nameof(ShutdownTest)); - logger.LogInformation("Started test: {testName}", nameof(ShutdownTest)); - - var applicationPath = Path.Combine(TestProjectHelpers.GetSolutionRoot(), "test", - "Microsoft.AspNetCore.Hosting.TestSites"); - - var deploymentParameters = new DeploymentParameters( - applicationPath, - ServerType.Kestrel, - RuntimeFlavor.CoreClr, - RuntimeArchitecture.x64) + using (StartLog(out var loggerFactory)) { - EnvironmentName = "Shutdown", - TargetFramework = "netcoreapp2.0", - ApplicationType = ApplicationType.Portable, - PublishApplicationBeforeDeployment = true - }; + var logger = loggerFactory.CreateLogger(nameof(ShutdownTest)); - using (var deployer = new SelfHostDeployer(deploymentParameters, logger)) - { - await deployer.DeployAsync(); + var applicationPath = Path.Combine(TestProjectHelpers.GetSolutionRoot(), "test", + "Microsoft.AspNetCore.Hosting.TestSites"); - // Wait for application to start - await Task.Delay(1000); + var deploymentParameters = new DeploymentParameters( + applicationPath, + ServerType.Kestrel, + RuntimeFlavor.CoreClr, + RuntimeArchitecture.x64) + { + EnvironmentName = "Shutdown", + TargetFramework = "netcoreapp2.0", + ApplicationType = ApplicationType.Portable, + PublishApplicationBeforeDeployment = true + }; - string output = string.Empty; - deployer.HostProcess.OutputDataReceived += (sender, args) => output += args.Data + '\n'; + using (var deployer = new SelfHostDeployer(deploymentParameters, loggerFactory)) + { + await deployer.DeployAsync(); - SendSIGINT(deployer.HostProcess.Id); + // Wait for application to start + await Task.Delay(1000); - WaitForExitOrKill(deployer.HostProcess); + string output = string.Empty; + deployer.HostProcess.OutputDataReceived += (sender, args) => output += args.Data + '\n'; - output = output.Trim('\n'); + SendSIGINT(deployer.HostProcess.Id); - Assert.Equal(output, "Application is shutting down...\n" + - "Stopping firing\n" + - "Stopping end\n" + - "Stopped firing\n" + - "Stopped end"); + WaitForExitOrKill(deployer.HostProcess); + + output = output.Trim('\n'); + + Assert.Equal(output, "Application is shutting down...\n" + + "Stopping firing\n" + + "Stopping end\n" + + "Stopped firing\n" + + "Stopped end"); + } } }