From 540b4e8f129a132749a60174464b8c8274bfed7d Mon Sep 17 00:00:00 2001 From: John Luo Date: Fri, 6 Mar 2020 14:59:15 -0800 Subject: [PATCH] Remove Serilog dependency in extensions (#3040) * Remove Serilog dependency in extensions * Add xunit logging for shutdown tests * Need to remove dependency on AspNetCore.Testing and remove DumpCollector --- azure-pipelines.yml | 2 - src/Caching/Memory/test/CapacityTests.cs | 14 +- ...oft.Extensions.Caching.Memory.Tests.csproj | 2 - ...tensions.Hosting.IntegrationTesting.csproj | 4 +- ....Extensions.Hosting.FunctionalTests.csproj | 5 +- .../test/FunctionalTests/ShutdownTests.cs | 103 +++--- .../Logging.Testing/src/AssemblyTestLog.cs | 306 ------------------ .../src/CollectDumpAttribute.cs | 40 --- .../DumpCollector/DumpCollector.Windows.cs | 77 ----- .../src/DumpCollector/DumpCollector.cs | 21 -- .../src/LoggedTest/ILoggedTest.cs | 25 -- .../src/LoggedTest/LoggedTest.cs | 26 -- .../src/LoggedTest/LoggedTestBase.cs | 122 ------- ...icrosoft.Extensions.Logging.Testing.csproj | 6 - .../src/TestFrameworkFileLoggerAttribute.cs | 18 -- ...Microsoft.Extensions.Logging.Testing.props | 30 -- .../test/AssemblyTestLogTests.cs | 221 ------------- .../test/LoggedTestXunitTests.cs | 193 ----------- ...ft.Extensions.Logging.Testing.Tests.csproj | 2 - 19 files changed, 62 insertions(+), 1155 deletions(-) delete mode 100644 src/Logging/Logging.Testing/src/AssemblyTestLog.cs delete mode 100644 src/Logging/Logging.Testing/src/CollectDumpAttribute.cs delete mode 100644 src/Logging/Logging.Testing/src/DumpCollector/DumpCollector.Windows.cs delete mode 100644 src/Logging/Logging.Testing/src/DumpCollector/DumpCollector.cs delete mode 100644 src/Logging/Logging.Testing/src/LoggedTest/ILoggedTest.cs delete mode 100644 src/Logging/Logging.Testing/src/LoggedTest/LoggedTest.cs delete mode 100644 src/Logging/Logging.Testing/src/LoggedTest/LoggedTestBase.cs delete mode 100644 src/Logging/Logging.Testing/src/TestFrameworkFileLoggerAttribute.cs delete mode 100644 src/Logging/Logging.Testing/src/build/Microsoft.Extensions.Logging.Testing.props delete mode 100644 src/Logging/Logging.Testing/test/AssemblyTestLogTests.cs delete mode 100644 src/Logging/Logging.Testing/test/LoggedTestXunitTests.cs diff --git a/azure-pipelines.yml b/azure-pipelines.yml index fc1a341a4e5..3739b57d1d6 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -140,8 +140,6 @@ stages: - script: eng\scripts\ci-flaky-tests.cmd -configuration $(_BuildConfig) displayName: Run Flaky Tests continueOnError: true - - script: dotnet msbuild eng/repo.targets /t:EnsureFunctionalTestLogsPreserved - displayName: Ensure functional test logs preserved - powershell: eng\scripts\KillProcesses.ps1 displayName: Kill processes condition: always() diff --git a/src/Caching/Memory/test/CapacityTests.cs b/src/Caching/Memory/test/CapacityTests.cs index 875bd861928..e21a9221dd6 100644 --- a/src/Caching/Memory/test/CapacityTests.cs +++ b/src/Caching/Memory/test/CapacityTests.cs @@ -1,4 +1,4 @@ -// Licensed to the .NET Foundation under one or more agreements. +// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. @@ -12,7 +12,7 @@ namespace Microsoft.Extensions.Caching.Memory { - public class CapacityTests : LoggedTestBase + public class CapacityTests { [Fact] public void MemoryDistributedCacheOptionsDefaultsTo200MBSizeLimit() @@ -112,13 +112,9 @@ public void DoNotAddEntryIfItExceedsCapacity() } [Fact] - [CollectDump] public async Task DoNotAddIfSizeOverflows() { - var cache = new MemoryCache(new MemoryCacheOptions - { - SizeLimit = long.MaxValue - }, LoggerFactory); + var cache = new MemoryCache(new MemoryCacheOptions { SizeLimit = long.MaxValue }); var entryOptions = new MemoryCacheEntryOptions { Size = long.MaxValue }; var sem = new SemaphoreSlim(0, 1); @@ -148,7 +144,6 @@ public async Task DoNotAddIfSizeOverflows() } [Fact] - [CollectDump] public async Task ExceedsCapacityCompacts() { var cache = new MemoryCache(new MemoryCacheOptions @@ -242,7 +237,6 @@ public void AddingReplacementWhenTotalSizeExceedsCapacityDoesNotUpdateAndRemoves } [Fact] - [CollectDump] public async Task AddingReplacementWhenTotalSizeExceedsCapacityDoesNotUpdateRemovesOldEntryAndTriggersCompaction() { var cache = new MemoryCache(new MemoryCacheOptions @@ -312,7 +306,6 @@ public void RemovingEntryDecreasesCacheSize() } [Fact] - [CollectDump] public async Task ExpiringEntryDecreasesCacheSize() { var cache = new MemoryCache(new MemoryCacheOptions @@ -348,7 +341,6 @@ public async Task ExpiringEntryDecreasesCacheSize() } [Fact] - [CollectDump] public async Task CompactsToLessThanLowWatermarkUsingLRUWhenHighWatermarkExceeded() { var testClock = new TestClock(); diff --git a/src/Caching/Memory/test/Microsoft.Extensions.Caching.Memory.Tests.csproj b/src/Caching/Memory/test/Microsoft.Extensions.Caching.Memory.Tests.csproj index a0fee41c97d..8e88b143593 100644 --- a/src/Caching/Memory/test/Microsoft.Extensions.Caching.Memory.Tests.csproj +++ b/src/Caching/Memory/test/Microsoft.Extensions.Caching.Memory.Tests.csproj @@ -1,7 +1,5 @@ - - $(DefaultNetCoreTargetFramework);net472 diff --git a/src/Hosting/IntegrationTesting/src/Microsoft.Extensions.Hosting.IntegrationTesting.csproj b/src/Hosting/IntegrationTesting/src/Microsoft.Extensions.Hosting.IntegrationTesting.csproj index cc2f6240318..2d8f5ebb456 100644 --- a/src/Hosting/IntegrationTesting/src/Microsoft.Extensions.Hosting.IntegrationTesting.csproj +++ b/src/Hosting/IntegrationTesting/src/Microsoft.Extensions.Hosting.IntegrationTesting.csproj @@ -15,12 +15,12 @@ + + - - diff --git a/src/Hosting/test/FunctionalTests/Microsoft.Extensions.Hosting.FunctionalTests.csproj b/src/Hosting/test/FunctionalTests/Microsoft.Extensions.Hosting.FunctionalTests.csproj index 90e743f6418..0cad57a32b5 100644 --- a/src/Hosting/test/FunctionalTests/Microsoft.Extensions.Hosting.FunctionalTests.csproj +++ b/src/Hosting/test/FunctionalTests/Microsoft.Extensions.Hosting.FunctionalTests.csproj @@ -1,6 +1,4 @@ - - - + $(DefaultNetCoreTargetFramework);net472 @@ -8,6 +6,7 @@ + diff --git a/src/Hosting/test/FunctionalTests/ShutdownTests.cs b/src/Hosting/test/FunctionalTests/ShutdownTests.cs index e6268cd6644..d22f45932d4 100644 --- a/src/Hosting/test/FunctionalTests/ShutdownTests.cs +++ b/src/Hosting/test/FunctionalTests/ShutdownTests.cs @@ -6,23 +6,29 @@ using System.Diagnostics; using System.IO; using System.Runtime.InteropServices; -using System.Threading; using System.Threading.Tasks; using Microsoft.AspNetCore.Testing; using Microsoft.Extensions.Hosting.IntegrationTesting; -using Microsoft.Extensions.Logging.Testing; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging.Test; using Xunit; using Xunit.Abstractions; namespace Microsoft.AspNetCore.Hosting.FunctionalTests { - public class ShutdownTests : LoggedTest + public class ShutdownTests { private static readonly string StartedMessage = "Started"; private static readonly string CompletionMessage = "Stopping firing\n" + "Stopping end\n" + "Stopped firing\n" + "Stopped end"; + private readonly ITestOutputHelper _output; + + public ShutdownTests(ITestOutputHelper output) + { + _output = output; + } [ConditionalFact] [OSSkipCondition(OperatingSystems.Windows | OperatingSystems.MacOSX)] @@ -40,67 +46,68 @@ public async Task ShutdownTestWaitForShutdown() private async Task ExecuteShutdownTest(string testName, string shutdownMechanic) { - using (StartLog(out var loggerFactory)) + var xunitTestLoggerFactory = TestLoggerBuilder.Create(builder => { - var logger = loggerFactory.CreateLogger(testName); + builder.SetMinimumLevel(LogLevel.Trace); + builder.AddXunit(_output); + }); - // TODO refactor deployers to not depend on source code - // see https://github.com/dotnet/extensions/issues/1697 and https://github.com/dotnet/aspnetcore/issues/10268 + // TODO refactor deployers to not depend on source code + // see https://github.com/dotnet/extensions/issues/1697 and https://github.com/dotnet/aspnetcore/issues/10268 #pragma warning disable 0618 - var applicationPath = Path.Combine(TestPathUtilities.GetSolutionRootDirectory("Extensions"), - "src", "Hosting", "test", "testassets", "Microsoft.Extensions.Hosting.TestApp"); + var applicationPath = Path.Combine(TestPathUtilities.GetSolutionRootDirectory("Extensions"), + "src", "Hosting", "test", "testassets", "Microsoft.Extensions.Hosting.TestApp"); #pragma warning restore 0618 - var deploymentParameters = new DeploymentParameters( - applicationPath, - RuntimeFlavor.CoreClr, - RuntimeArchitecture.x64) - { - TargetFramework = Tfm.NetCoreApp50, - ApplicationType = ApplicationType.Portable, - PublishApplicationBeforeDeployment = true, - StatusMessagesEnabled = false - }; + var deploymentParameters = new DeploymentParameters( + applicationPath, + RuntimeFlavor.CoreClr, + RuntimeArchitecture.x64) + { + TargetFramework = Tfm.NetCoreApp50, + ApplicationType = ApplicationType.Portable, + PublishApplicationBeforeDeployment = true, + StatusMessagesEnabled = false + }; - deploymentParameters.EnvironmentVariables["DOTNET_STARTMECHANIC"] = shutdownMechanic; + deploymentParameters.EnvironmentVariables["DOTNET_STARTMECHANIC"] = shutdownMechanic; - using (var deployer = new SelfHostDeployer(deploymentParameters, loggerFactory)) - { - var result = await deployer.DeployAsync(); + using (var deployer = new SelfHostDeployer(deploymentParameters, xunitTestLoggerFactory)) + { + var result = await deployer.DeployAsync(); - var started = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); - var completed = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); - var output = string.Empty; - deployer.HostProcess.OutputDataReceived += (sender, args) => + var started = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); + var completed = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); + var output = string.Empty; + deployer.HostProcess.OutputDataReceived += (sender, args) => + { + if (!string.IsNullOrEmpty(args.Data) && args.Data.StartsWith(StartedMessage)) { - if (!string.IsNullOrEmpty(args.Data) && args.Data.StartsWith(StartedMessage)) - { - output += args.Data.Substring(StartedMessage.Length) + '\n'; - started.TrySetResult(0); - } - else - { - output += args.Data + '\n'; - } + output += args.Data.Substring(StartedMessage.Length) + '\n'; + started.TrySetResult(0); + } + else + { + output += args.Data + '\n'; + } - if (output.Contains(CompletionMessage)) - { - completed.TrySetResult(0); - } - }; + if (output.Contains(CompletionMessage)) + { + completed.TrySetResult(0); + } + }; - await started.Task.TimeoutAfter(TimeSpan.FromSeconds(60)); + await started.Task.TimeoutAfter(TimeSpan.FromSeconds(60)); - SendShutdownSignal(deployer.HostProcess); + SendShutdownSignal(deployer.HostProcess); - await completed.Task.TimeoutAfter(TimeSpan.FromSeconds(60)); + await completed.Task.TimeoutAfter(TimeSpan.FromSeconds(60)); - WaitForExitOrKill(deployer.HostProcess); + WaitForExitOrKill(deployer.HostProcess); - output = output.Trim('\n'); + output = output.Trim('\n'); - Assert.Equal(CompletionMessage, output); - } + Assert.Equal(CompletionMessage, output); } } diff --git a/src/Logging/Logging.Testing/src/AssemblyTestLog.cs b/src/Logging/Logging.Testing/src/AssemblyTestLog.cs deleted file mode 100644 index bd69cd20a3e..00000000000 --- a/src/Logging/Logging.Testing/src/AssemblyTestLog.cs +++ /dev/null @@ -1,306 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.IO; -using System.Linq; -using System.Reflection; -using System.Runtime.CompilerServices; -using System.Text; -using Microsoft.AspNetCore.Testing; -using Microsoft.Extensions.DependencyInjection; -using Serilog; -using Serilog.Core; -using Serilog.Events; -using Serilog.Extensions.Logging; -using Xunit.Abstractions; - -namespace Microsoft.Extensions.Logging.Testing -{ - public class AssemblyTestLog : IDisposable - { - private static readonly string MaxPathLengthEnvironmentVariableName = "ASPNETCORE_TEST_LOG_MAXPATH"; - private static readonly string LogFileExtension = ".log"; - private static readonly int MaxPathLength = GetMaxPathLength(); - - private static readonly object _lock = new object(); - private static readonly Dictionary _logs = new Dictionary(); - - private readonly ILoggerFactory _globalLoggerFactory; - private readonly ILogger _globalLogger; - private readonly string _baseDirectory; - private readonly Assembly _assembly; - private readonly IServiceProvider _serviceProvider; - - private static int GetMaxPathLength() - { - var maxPathString = Environment.GetEnvironmentVariable(MaxPathLengthEnvironmentVariableName); - var defaultMaxPath = 245; - return string.IsNullOrEmpty(maxPathString) ? defaultMaxPath : int.Parse(maxPathString); - } - - private AssemblyTestLog(ILoggerFactory globalLoggerFactory, ILogger globalLogger, string baseDirectory, Assembly assembly, IServiceProvider serviceProvider) - { - _globalLoggerFactory = globalLoggerFactory; - _globalLogger = globalLogger; - _baseDirectory = baseDirectory; - _assembly = assembly; - _serviceProvider = serviceProvider; - } - - public IDisposable StartTestLog(ITestOutputHelper output, string className, out ILoggerFactory loggerFactory, [CallerMemberName] string testName = null) => - StartTestLog(output, className, out loggerFactory, LogLevel.Debug, testName); - - public IDisposable StartTestLog(ITestOutputHelper output, string className, out ILoggerFactory loggerFactory, LogLevel minLogLevel, [CallerMemberName] string testName = null) => - StartTestLog(output, className, out loggerFactory, minLogLevel, out var _, out var _, testName); - - internal IDisposable StartTestLog(ITestOutputHelper output, string className, out ILoggerFactory loggerFactory, LogLevel minLogLevel, out string resolvedTestName, out string logOutputDirectory, [CallerMemberName] string testName = null) - { - var logStart = DateTimeOffset.UtcNow; - var serviceProvider = CreateLoggerServices(output, className, minLogLevel, out resolvedTestName, out logOutputDirectory, testName, logStart); - var factory = serviceProvider.GetRequiredService(); - loggerFactory = factory; - var logger = loggerFactory.CreateLogger("TestLifetime"); - - var stopwatch = Stopwatch.StartNew(); - - var scope = logger.BeginScope("Test: {testName}", testName); - - _globalLogger.LogInformation("Starting test {testName}", testName); - logger.LogInformation("Starting test {testName} at {logStart}", testName, logStart.ToString("s")); - - 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); - scope.Dispose(); - factory.Dispose(); - (serviceProvider as IDisposable)?.Dispose(); - }); - } - - public ILoggerFactory CreateLoggerFactory(ITestOutputHelper output, string className, [CallerMemberName] string testName = null, DateTimeOffset? logStart = null) - => CreateLoggerFactory(output, className, LogLevel.Trace, testName, logStart); - - public ILoggerFactory CreateLoggerFactory(ITestOutputHelper output, string className, LogLevel minLogLevel, [CallerMemberName] string testName = null, DateTimeOffset? logStart = null) - => CreateLoggerServices(output, className, minLogLevel, out var _, out var _, testName, logStart).GetRequiredService(); - - public IServiceProvider CreateLoggerServices(ITestOutputHelper output, string className, LogLevel minLogLevel, out string normalizedTestName, [CallerMemberName] string testName = null, DateTimeOffset? logStart = null) - => CreateLoggerServices(output, className, minLogLevel, out normalizedTestName, out var _, testName, logStart); - - public IServiceProvider CreateLoggerServices(ITestOutputHelper output, string className, LogLevel minLogLevel, out string normalizedTestName, out string logOutputDirectory, [CallerMemberName] string testName = null, DateTimeOffset? logStart = null) - { - normalizedTestName = string.Empty; - logOutputDirectory = string.Empty; - var assemblyName = _assembly.GetName().Name; - - // Try to shorten the class name using the assembly name - if (className.StartsWith(assemblyName + ".")) - { - className = className.Substring(assemblyName.Length + 1); - } - - SerilogLoggerProvider serilogLoggerProvider = null; - if (!string.IsNullOrEmpty(_baseDirectory)) - { - logOutputDirectory = Path.Combine(_baseDirectory, className); - testName = TestFileOutputContext.RemoveIllegalFileChars(testName); - - if (logOutputDirectory.Length + testName.Length + LogFileExtension.Length >= MaxPathLength) - { - _globalLogger.LogWarning($"Test name {testName} is too long. Please shorten test name."); - - // Shorten the test name by removing the middle portion of the testname - var testNameLength = MaxPathLength - logOutputDirectory.Length - LogFileExtension.Length; - - if (testNameLength <= 0) - { - throw new InvalidOperationException("Output file path could not be constructed due to max path length restrictions. Please shorten test assembly, class or method names."); - } - - testName = testName.Substring(0, testNameLength / 2) + testName.Substring(testName.Length - testNameLength / 2, testNameLength / 2); - - _globalLogger.LogWarning($"To prevent long paths test name was shortened to {testName}."); - } - - var testOutputFile = Path.Combine(logOutputDirectory, $"{testName}{LogFileExtension}"); - - if (File.Exists(testOutputFile)) - { - _globalLogger.LogWarning($"Output log file {testOutputFile} already exists. Please try to keep log file names unique."); - - for (var i = 0; i < 1000; i++) - { - testOutputFile = Path.Combine(logOutputDirectory, $"{testName}.{i}{LogFileExtension}"); - - if (!File.Exists(testOutputFile)) - { - _globalLogger.LogWarning($"To resolve log file collision, the enumerated file {testOutputFile} will be used."); - testName = $"{testName}.{i}"; - break; - } - } - } - - normalizedTestName = testName; - serilogLoggerProvider = ConfigureFileLogging(testOutputFile, logStart); - } - - var serviceCollection = new ServiceCollection(); - serviceCollection.AddLogging(builder => - { - builder.SetMinimumLevel(minLogLevel); - - if (output != null) - { - builder.AddXunit(output, minLogLevel, logStart); - } - - if (serilogLoggerProvider != null) - { - // Use a factory so that the container will dispose it - builder.Services.AddSingleton(_ => serilogLoggerProvider); - } - }); - - return serviceCollection.BuildServiceProvider(); - } - - // For back compat - public static AssemblyTestLog Create(string assemblyName, string baseDirectory) - => Create(Assembly.Load(new AssemblyName(assemblyName)), baseDirectory); - - public static AssemblyTestLog Create(Assembly assembly, string baseDirectory) - { - var logStart = DateTimeOffset.UtcNow; - SerilogLoggerProvider serilogLoggerProvider = null; - if (!string.IsNullOrEmpty(baseDirectory)) - { - baseDirectory = TestFileOutputContext.GetAssemblyBaseDirectory(assembly, baseDirectory); - var globalLogFileName = Path.Combine(baseDirectory, "global.log"); - serilogLoggerProvider = ConfigureFileLogging(globalLogFileName, logStart); - } - - var serviceCollection = new ServiceCollection(); - - serviceCollection.AddLogging(builder => - { - // Global logging, when it's written, is expected to be outputted. So set the log level to minimum. - builder.SetMinimumLevel(LogLevel.Trace); - - if (serilogLoggerProvider != null) - { - // Use a factory so that the container will dispose it - builder.Services.AddSingleton(_ => serilogLoggerProvider); - } - }); - - var serviceProvider = serviceCollection.BuildServiceProvider(); - var loggerFactory = serviceProvider.GetRequiredService(); - - var logger = loggerFactory.CreateLogger("GlobalTestLog"); - logger.LogInformation("Global Test Logging initialized at {logStart}. " - + "Configure the output directory via 'LoggingTestingFileLoggingDirectory' MSBuild property " - + "or set 'LoggingTestingDisableFileLogging' to 'true' to disable file logging.", - logStart.ToString("s")); - return new AssemblyTestLog(loggerFactory, logger, baseDirectory, assembly, serviceProvider); - } - - public static AssemblyTestLog ForAssembly(Assembly assembly) - { - lock (_lock) - { - if (!_logs.TryGetValue(assembly, out var log)) - { - var baseDirectory = TestFileOutputContext.GetOutputDirectory(assembly); - - log = Create(assembly, baseDirectory); - _logs[assembly] = log; - - // Try to clear previous logs, continue if it fails. - var assemblyBaseDirectory = TestFileOutputContext.GetAssemblyBaseDirectory(assembly); - if (!string.IsNullOrEmpty(assemblyBaseDirectory) && !TestFileOutputContext.GetPreserveExistingLogsInOutput(assembly)) - { - try - { - Directory.Delete(assemblyBaseDirectory, recursive: true); - } - catch { } - } - } - return log; - } - } - - private static TestFrameworkFileLoggerAttribute GetFileLoggerAttribute(Assembly assembly) - => assembly.GetCustomAttribute() - ?? throw new InvalidOperationException($"No {nameof(TestFrameworkFileLoggerAttribute)} found on the assembly {assembly.GetName().Name}. " - + "The attribute is added via msbuild properties of the Microsoft.Extensions.Logging.Testing. " - + "Please ensure the msbuild property is imported or a direct reference to Microsoft.Extensions.Logging.Testing is added."); - - private static SerilogLoggerProvider ConfigureFileLogging(string fileName, DateTimeOffset? logStart) - { - 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() - .Enrich.With(new AssemblyLogTimestampOffsetEnricher(logStart)) - .MinimumLevel.Verbose() - .WriteTo.File(fileName, outputTemplate: "[{TimestampOffset}] [{SourceContext}] [{Level}] {Message:l}{NewLine}{Exception}", flushToDiskInterval: TimeSpan.FromSeconds(1), shared: true) - .CreateLogger(); - return new SerilogLoggerProvider(serilogger, dispose: true); - } - - public void Dispose() - { - (_serviceProvider as IDisposable)?.Dispose(); - _globalLoggerFactory.Dispose(); - } - - private class AssemblyLogTimestampOffsetEnricher : ILogEventEnricher - { - private DateTimeOffset? _logStart; - - public AssemblyLogTimestampOffsetEnricher(DateTimeOffset? logStart) - { - _logStart = logStart; - } - - public void Enrich(LogEvent logEvent, ILogEventPropertyFactory propertyFactory) - => logEvent.AddPropertyIfAbsent( - propertyFactory.CreateProperty( - "TimestampOffset", - _logStart.HasValue - ? $"{(DateTimeOffset.UtcNow - _logStart.Value).TotalSeconds.ToString("N3")}s" - : DateTimeOffset.UtcNow.ToString("s"))); - } - - private class Disposable : IDisposable - { - private Action _action; - - public Disposable(Action action) - { - _action = action; - } - - public void Dispose() - { - _action(); - } - } - } -} diff --git a/src/Logging/Logging.Testing/src/CollectDumpAttribute.cs b/src/Logging/Logging.Testing/src/CollectDumpAttribute.cs deleted file mode 100644 index 5f4a1eee590..00000000000 --- a/src/Logging/Logging.Testing/src/CollectDumpAttribute.cs +++ /dev/null @@ -1,40 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -using System; -using System.Diagnostics; -using System.IO; -using System.Threading; -using System.Threading.Tasks; -using Microsoft.AspNetCore.Testing; - -namespace Microsoft.Extensions.Logging.Testing -{ - /// - /// Capture the memory dump upon test failure. - /// - /// - /// This currently only works in Windows environments - /// - [AttributeUsage(AttributeTargets.Method, AllowMultiple = false)] - public class CollectDumpAttribute : Attribute, ITestMethodLifecycle - { - public Task OnTestStartAsync(TestContext context, CancellationToken cancellationToken) - { - return Task.CompletedTask; - } - - public Task OnTestEndAsync(TestContext context, Exception exception, CancellationToken cancellationToken) - { - if (exception != null) - { - var path = Path.Combine(context.FileOutput.TestClassOutputDirectory, context.FileOutput.GetUniqueFileName(context.FileOutput.TestName, ".dmp")); - var process = Process.GetCurrentProcess(); - DumpCollector.Collect(process, path); - } - - return Task.CompletedTask; - } - } -} diff --git a/src/Logging/Logging.Testing/src/DumpCollector/DumpCollector.Windows.cs b/src/Logging/Logging.Testing/src/DumpCollector/DumpCollector.Windows.cs deleted file mode 100644 index 20395208d7c..00000000000 --- a/src/Logging/Logging.Testing/src/DumpCollector/DumpCollector.Windows.cs +++ /dev/null @@ -1,77 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -using System; -using System.Diagnostics; -using System.IO; -using System.Runtime.InteropServices; -using Microsoft.Win32.SafeHandles; - -namespace Microsoft.Extensions.Logging.Testing -{ - public static partial class DumpCollector - { - private static class Windows - { - internal static void Collect(Process process, string outputFile) - { - // Open the file for writing - using (var stream = new FileStream(outputFile, FileMode.Create, FileAccess.ReadWrite, FileShare.None)) - { - // Dump the process! - var exceptionInfo = new NativeMethods.MINIDUMP_EXCEPTION_INFORMATION(); - if (!NativeMethods.MiniDumpWriteDump(process.Handle, (uint)process.Id, stream.SafeFileHandle, NativeMethods.MINIDUMP_TYPE.MiniDumpWithFullMemory, ref exceptionInfo, IntPtr.Zero, IntPtr.Zero)) - { - var err = Marshal.GetHRForLastWin32Error(); - Marshal.ThrowExceptionForHR(err); - } - } - } - - private static class NativeMethods - { - [DllImport("Dbghelp.dll")] - public static extern bool MiniDumpWriteDump(IntPtr hProcess, uint ProcessId, SafeFileHandle hFile, MINIDUMP_TYPE DumpType, ref MINIDUMP_EXCEPTION_INFORMATION ExceptionParam, IntPtr UserStreamParam, IntPtr CallbackParam); - - [StructLayout(LayoutKind.Sequential, Pack = 4)] - public struct MINIDUMP_EXCEPTION_INFORMATION - { - public uint ThreadId; - public IntPtr ExceptionPointers; - public int ClientPointers; - } - - [Flags] - public enum MINIDUMP_TYPE : uint - { - MiniDumpNormal = 0, - MiniDumpWithDataSegs = 1 << 0, - MiniDumpWithFullMemory = 1 << 1, - MiniDumpWithHandleData = 1 << 2, - MiniDumpFilterMemory = 1 << 3, - MiniDumpScanMemory = 1 << 4, - MiniDumpWithUnloadedModules = 1 << 5, - MiniDumpWithIndirectlyReferencedMemory = 1 << 6, - MiniDumpFilterModulePaths = 1 << 7, - MiniDumpWithProcessThreadData = 1 << 8, - MiniDumpWithPrivateReadWriteMemory = 1 << 9, - MiniDumpWithoutOptionalData = 1 << 10, - MiniDumpWithFullMemoryInfo = 1 << 11, - MiniDumpWithThreadInfo = 1 << 12, - MiniDumpWithCodeSegs = 1 << 13, - MiniDumpWithoutAuxiliaryState = 1 << 14, - MiniDumpWithFullAuxiliaryState = 1 << 15, - MiniDumpWithPrivateWriteCopyMemory = 1 << 16, - MiniDumpIgnoreInaccessibleMemory = 1 << 17, - MiniDumpWithTokenInformation = 1 << 18, - MiniDumpWithModuleHeaders = 1 << 19, - MiniDumpFilterTriage = 1 << 20, - MiniDumpWithAvxXStateContext = 1 << 21, - MiniDumpWithIptTrace = 1 << 22, - MiniDumpValidTypeFlags = (-1) ^ ((~1) << 22) - } - } - } - } -} diff --git a/src/Logging/Logging.Testing/src/DumpCollector/DumpCollector.cs b/src/Logging/Logging.Testing/src/DumpCollector/DumpCollector.cs deleted file mode 100644 index d67e109b383..00000000000 --- a/src/Logging/Logging.Testing/src/DumpCollector/DumpCollector.cs +++ /dev/null @@ -1,21 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -using System.Diagnostics; -using System.Runtime.InteropServices; - -namespace Microsoft.Extensions.Logging.Testing -{ - public static partial class DumpCollector - { - public static void Collect(Process process, string fileName) - { - if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) - { - Windows.Collect(process, fileName); - } - // No implementations yet for macOS and Linux - } - } -} diff --git a/src/Logging/Logging.Testing/src/LoggedTest/ILoggedTest.cs b/src/Logging/Logging.Testing/src/LoggedTest/ILoggedTest.cs deleted file mode 100644 index 750f45cd912..00000000000 --- a/src/Logging/Logging.Testing/src/LoggedTest/ILoggedTest.cs +++ /dev/null @@ -1,25 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -using System; -using System.Reflection; -using Microsoft.AspNetCore.Testing; -using Xunit.Abstractions; - -namespace Microsoft.Extensions.Logging.Testing -{ - public interface ILoggedTest : IDisposable - { - ILogger Logger { get; } - - ILoggerFactory LoggerFactory { get; } - - ITestOutputHelper TestOutputHelper { get; } - - // For back compat - IDisposable StartLog(out ILoggerFactory loggerFactory, LogLevel minLogLevel, string testName); - - void Initialize(TestContext context, MethodInfo methodInfo, object[] testMethodArguments, ITestOutputHelper testOutputHelper); - } -} diff --git a/src/Logging/Logging.Testing/src/LoggedTest/LoggedTest.cs b/src/Logging/Logging.Testing/src/LoggedTest/LoggedTest.cs deleted file mode 100644 index 169a94f59d6..00000000000 --- a/src/Logging/Logging.Testing/src/LoggedTest/LoggedTest.cs +++ /dev/null @@ -1,26 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -using System.Reflection; -using Microsoft.AspNetCore.Testing; -using Xunit.Abstractions; - -namespace Microsoft.Extensions.Logging.Testing -{ - public class LoggedTest : LoggedTestBase - { - // Obsolete but keeping for back compat - public LoggedTest(ITestOutputHelper output = null) : base (output) { } - - public ITestSink TestSink { get; set; } - - public override void Initialize(TestContext context, MethodInfo methodInfo, object[] testMethodArguments, ITestOutputHelper testOutputHelper) - { - base.Initialize(context, methodInfo, testMethodArguments, testOutputHelper); - - TestSink = new TestSink(); - LoggerFactory.AddProvider(new TestLoggerProvider(TestSink)); - } - } -} diff --git a/src/Logging/Logging.Testing/src/LoggedTest/LoggedTestBase.cs b/src/Logging/Logging.Testing/src/LoggedTest/LoggedTestBase.cs deleted file mode 100644 index 16dde9676c5..00000000000 --- a/src/Logging/Logging.Testing/src/LoggedTest/LoggedTestBase.cs +++ /dev/null @@ -1,122 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -using System; -using System.Linq; -using System.Reflection; -using System.Runtime.CompilerServices; -using System.Runtime.ExceptionServices; -using System.Threading; -using System.Threading.Tasks; -using Microsoft.AspNetCore.Testing; -using Microsoft.Extensions.DependencyInjection; -using Serilog; -using Xunit.Abstractions; - -namespace Microsoft.Extensions.Logging.Testing -{ - public class LoggedTestBase : ILoggedTest, ITestMethodLifecycle - { - private ExceptionDispatchInfo _initializationException; - - private IDisposable _testLog; - - // Obsolete but keeping for back compat - public LoggedTestBase(ITestOutputHelper output = null) - { - TestOutputHelper = output; - } - - protected TestContext Context { get; private set; } - - // Internal for testing - internal string ResolvedTestClassName { get; set; } - - public string ResolvedLogOutputDirectory { get; set; } - - public string ResolvedTestMethodName { get; set; } - - public ILogger Logger { get; set; } - - public ILoggerFactory LoggerFactory { get; set; } - - public ITestOutputHelper TestOutputHelper { get; set; } - - public void AddTestLogging(IServiceCollection services) => services.AddSingleton(LoggerFactory); - - // For back compat - public IDisposable StartLog(out ILoggerFactory loggerFactory, [CallerMemberName] string testName = null) => StartLog(out loggerFactory, LogLevel.Debug, testName); - - // For back compat - public IDisposable StartLog(out ILoggerFactory loggerFactory, LogLevel minLogLevel, [CallerMemberName] string testName = null) - { - return AssemblyTestLog.ForAssembly(GetType().GetTypeInfo().Assembly).StartTestLog(TestOutputHelper, GetType().FullName, out loggerFactory, minLogLevel, testName); - } - - public virtual void Initialize(TestContext context, MethodInfo methodInfo, object[] testMethodArguments, ITestOutputHelper testOutputHelper) - { - try - { - TestOutputHelper = testOutputHelper; - - var classType = GetType(); - var logLevelAttribute = methodInfo.GetCustomAttribute() - ?? methodInfo.DeclaringType.GetCustomAttribute() - ?? methodInfo.DeclaringType.Assembly.GetCustomAttribute(); - - // internal for testing - ResolvedTestClassName = context.FileOutput.TestClassName; - - _testLog = AssemblyTestLog - .ForAssembly(classType.GetTypeInfo().Assembly) - .StartTestLog( - TestOutputHelper, - context.FileOutput.TestClassName, - out var loggerFactory, - logLevelAttribute?.LogLevel ?? LogLevel.Debug, - out var resolvedTestName, - out var logDirectory, - context.FileOutput.TestName); - - ResolvedLogOutputDirectory = logDirectory; - ResolvedTestMethodName = resolvedTestName; - - LoggerFactory = loggerFactory; - Logger = loggerFactory.CreateLogger(classType); - } - catch (Exception e) - { - _initializationException = ExceptionDispatchInfo.Capture(e); - } - } - - public virtual void Dispose() - { - if (_testLog == null) - { - // It seems like sometimes the MSBuild goop that adds the test framework can end up in a bad state and not actually add it - // Not sure yet why that happens but the exception isn't clear so I'm adding this error so we can detect it better. - // -anurse - throw new InvalidOperationException("LoggedTest base class was used but nothing initialized it! The test framework may not be enabled. Try cleaning your 'obj' directory."); - } - - _initializationException?.Throw(); - _testLog.Dispose(); - } - - Task ITestMethodLifecycle.OnTestStartAsync(TestContext context, CancellationToken cancellationToken) - { - - Context = context; - - Initialize(context, context.TestMethod, context.MethodArguments, context.Output); - return Task.CompletedTask; - } - - Task ITestMethodLifecycle.OnTestEndAsync(TestContext context, Exception exception, CancellationToken cancellationToken) - { - return Task.CompletedTask; - } - } -} diff --git a/src/Logging/Logging.Testing/src/Microsoft.Extensions.Logging.Testing.csproj b/src/Logging/Logging.Testing/src/Microsoft.Extensions.Logging.Testing.csproj index 0c07c01c103..457843ba64a 100644 --- a/src/Logging/Logging.Testing/src/Microsoft.Extensions.Logging.Testing.csproj +++ b/src/Logging/Logging.Testing/src/Microsoft.Extensions.Logging.Testing.csproj @@ -18,12 +18,9 @@ - - - - $(RepositoryRoot) - $(ASPNETCORE_TEST_LOG_DIR) - $(RepoRoot)artifacts\log\ - - - - - true - false - - - - - <_Parameter1>Microsoft.AspNetCore.Testing.AspNetTestFramework - <_Parameter2>Microsoft.AspNetCore.Testing - - - - <_Parameter1>$(PreserveExistingLogsInOutput) - <_Parameter2>$(TargetFramework) - <_Parameter3 Condition="'$(LoggingTestingDisableFileLogging)' != 'true'">$(LoggingTestingFileLoggingDirectory) - - - - diff --git a/src/Logging/Logging.Testing/test/AssemblyTestLogTests.cs b/src/Logging/Logging.Testing/test/AssemblyTestLogTests.cs deleted file mode 100644 index 27a7cf83cf6..00000000000 --- a/src/Logging/Logging.Testing/test/AssemblyTestLogTests.cs +++ /dev/null @@ -1,221 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -using System; -using System.IO; -using System.Linq; -using System.Reflection; -using System.Runtime.CompilerServices; -using System.Text.RegularExpressions; -using System.Threading.Tasks; -using Microsoft.AspNetCore.Testing; -using Xunit; - -namespace Microsoft.Extensions.Logging.Testing.Tests -{ - public class AssemblyTestLogTests : LoggedTest - { - private static readonly Assembly ThisAssembly = typeof(AssemblyTestLogTests).GetTypeInfo().Assembly; - private static readonly string ThisAssemblyName = ThisAssembly.GetName().Name; - private static readonly string TFM = new DirectoryInfo(AppContext.BaseDirectory).Name; - - [Fact] - public void FunctionalLogs_LogsPreservedFromNonFlakyRun() - { - } - - [Fact] - [Flaky("http://example.com", FlakyOn.All)] - public void FunctionalLogs_LogsPreservedFromFlakyRun() - { - } - - [Fact] - public void ForAssembly_ReturnsSameInstanceForSameAssembly() - { - Assert.Same( - AssemblyTestLog.ForAssembly(ThisAssembly), - AssemblyTestLog.ForAssembly(ThisAssembly)); - } - - [Fact] - public void TestLogWritesToITestOutputHelper() - { - var output = new TestTestOutputHelper(); - var assemblyLog = AssemblyTestLog.Create(ThisAssemblyName, baseDirectory: null); - - using (assemblyLog.StartTestLog(output, "NonExistant.Test.Class", out var loggerFactory)) - { - var logger = loggerFactory.CreateLogger("TestLogger"); - logger.LogInformation("Information!"); - - // Trace is disabled by default - logger.LogTrace("Trace!"); - } - - var testLogContent = MakeConsistent(output.Output); - - Assert.Equal( -@"[OFFSET] TestLifetime Information: Starting test TestLogWritesToITestOutputHelper at TIMESTAMP -[OFFSET] TestLogger Information: Information! -[OFFSET] TestLifetime Information: Finished test TestLogWritesToITestOutputHelper in DURATION -", testLogContent, ignoreLineEndingDifferences: true); - } - - [Fact] - public Task TestLogEscapesIllegalFileNames() => - RunTestLogFunctionalTest((tempDir) => - { - var illegalTestName = "T:e/s//t"; - var escapedTestName = "T_e_s_t"; - using (var testAssemblyLog = AssemblyTestLog.Create(ThisAssemblyName, baseDirectory: tempDir)) - using (testAssemblyLog.StartTestLog(output: null, className: "FakeTestAssembly.FakeTestClass", loggerFactory: out var testLoggerFactory, minLogLevel: LogLevel.Trace, resolvedTestName: out var resolvedTestname, out var _, testName: illegalTestName)) - { - Assert.Equal(escapedTestName, resolvedTestname); - } - }); - - [Fact] - public Task TestLogWritesToGlobalLogFile() => - RunTestLogFunctionalTest((tempDir) => - { - // Because this test writes to a file, it is a functional test and should be logged - // but it's also testing the test logging facility. So this is pretty meta ;) - var logger = LoggerFactory.CreateLogger("Test"); - - using (var testAssemblyLog = AssemblyTestLog.Create(ThisAssemblyName, tempDir)) - { - logger.LogInformation("Created test log in {baseDirectory}", tempDir); - - using (testAssemblyLog.StartTestLog(output: null, className: $"{ThisAssemblyName}.FakeTestClass", loggerFactory: out var testLoggerFactory, minLogLevel: LogLevel.Trace, testName: "FakeTestName")) - { - var testLogger = testLoggerFactory.CreateLogger("TestLogger"); - testLogger.LogInformation("Information!"); - testLogger.LogTrace("Trace!"); - } - } - - logger.LogInformation("Finished test log in {baseDirectory}", tempDir); - - var globalLogPath = Path.Combine(tempDir, ThisAssemblyName, TFM, "global.log"); - var testLog = Path.Combine(tempDir, ThisAssemblyName, TFM, "FakeTestClass", "FakeTestName.log"); - - Assert.True(File.Exists(globalLogPath), $"Expected global log file {globalLogPath} to exist"); - Assert.True(File.Exists(testLog), $"Expected test log file {testLog} to exist"); - - var globalLogContent = MakeConsistent(File.ReadAllText(globalLogPath)); - var testLogContent = MakeConsistent(File.ReadAllText(testLog)); - - Assert.Equal( -@"[OFFSET] [GlobalTestLog] [Information] Global Test Logging initialized at TIMESTAMP. Configure the output directory via 'LoggingTestingFileLoggingDirectory' MSBuild property or set 'LoggingTestingDisableFileLogging' to 'true' to disable file logging. -[OFFSET] [GlobalTestLog] [Information] Starting test FakeTestName -[OFFSET] [GlobalTestLog] [Information] Finished test FakeTestName in DURATION -", globalLogContent, ignoreLineEndingDifferences: true); - Assert.Equal( -@"[OFFSET] [TestLifetime] [Information] Starting test FakeTestName at TIMESTAMP -[OFFSET] [TestLogger] [Information] Information! -[OFFSET] [TestLogger] [Verbose] Trace! -[OFFSET] [TestLifetime] [Information] Finished test FakeTestName in DURATION -", testLogContent, ignoreLineEndingDifferences: true); - }); - - [Fact] - public Task TestLogTruncatesTestNameToAvoidLongPaths() => - RunTestLogFunctionalTest((tempDir) => - { - var longTestName = new string('0', 50) + new string('1', 50) + new string('2', 50) + new string('3', 50) + new string('4', 50); - var logger = LoggerFactory.CreateLogger("Test"); - using (var testAssemblyLog = AssemblyTestLog.Create(ThisAssemblyName, tempDir)) - { - logger.LogInformation("Created test log in {baseDirectory}", tempDir); - - using (testAssemblyLog.StartTestLog(output: null, className: $"{ThisAssemblyName}.FakeTestClass", loggerFactory: out var testLoggerFactory, minLogLevel: LogLevel.Trace, testName: longTestName)) - { - testLoggerFactory.CreateLogger("TestLogger").LogInformation("Information!"); - } - } - logger.LogInformation("Finished test log in {baseDirectory}", tempDir); - - var testLogFiles = new DirectoryInfo(Path.Combine(tempDir, ThisAssemblyName, TFM, "FakeTestClass")).EnumerateFiles(); - var testLog = Assert.Single(testLogFiles); - var testFileName = Path.GetFileNameWithoutExtension(testLog.Name); - - // The first half of the file comes from the beginning of the test name passed to the logger - Assert.Equal(longTestName.Substring(0, testFileName.Length / 2), testFileName.Substring(0, testFileName.Length / 2)); - // The last half of the file comes from the ending of the test name passed to the logger - Assert.Equal(longTestName.Substring(longTestName.Length - testFileName.Length / 2, testFileName.Length / 2), testFileName.Substring(testFileName.Length - testFileName.Length / 2, testFileName.Length / 2)); - }); - - [Fact] - public Task TestLogEnumerateFilenamesToAvoidCollisions() => - RunTestLogFunctionalTest((tempDir) => - { - var logger = LoggerFactory.CreateLogger("Test"); - using (var testAssemblyLog = AssemblyTestLog.Create(ThisAssemblyName, tempDir)) - { - logger.LogInformation("Created test log in {baseDirectory}", tempDir); - - for (var i = 0; i < 10; i++) - { - using (testAssemblyLog.StartTestLog(output: null, className: $"{ThisAssemblyName}.FakeTestClass", loggerFactory: out var testLoggerFactory, minLogLevel: LogLevel.Trace, testName: "FakeTestName")) - { - testLoggerFactory.CreateLogger("TestLogger").LogInformation("Information!"); - } - } - } - logger.LogInformation("Finished test log in {baseDirectory}", tempDir); - - // The first log file exists - Assert.True(File.Exists(Path.Combine(tempDir, ThisAssemblyName, TFM, "FakeTestClass", "FakeTestName.log"))); - - // Subsequent files exist - for (var i = 0; i < 9; i++) - { - Assert.True(File.Exists(Path.Combine(tempDir, ThisAssemblyName, TFM, "FakeTestClass", $"FakeTestName.{i}.log"))); - } - }); - - private static readonly Regex TimestampRegex = new Regex(@"\d+-\d+-\d+T\d+:\d+:\d+"); - private static readonly Regex TimestampOffsetRegex = new Regex(@"\d+\.\d+s"); - private static readonly Regex DurationRegex = new Regex(@"[^ ]+s$"); - - private async Task RunTestLogFunctionalTest(Action action, [CallerMemberName] string testName = null) - { - var tempDir = Path.Combine(Path.GetTempPath(), $"TestLogging_{Guid.NewGuid().ToString("N")}"); - try - { - action(tempDir); - } - finally - { - if (Directory.Exists(tempDir)) - { - try - { - Directory.Delete(tempDir, recursive: true); - } - catch - { - await Task.Delay(100); - Directory.Delete(tempDir, recursive: true); - } - } - } - } - - private static string MakeConsistent(string input) - { - return string.Join(Environment.NewLine, input.Split(new[] { Environment.NewLine }, StringSplitOptions.None) - .Select(line => - { - var strippedPrefix = line.IndexOf("[") >= 0 ? line.Substring(line.IndexOf("[")) : line; - - var strippedDuration = DurationRegex.Replace(strippedPrefix, "DURATION"); - var strippedTimestamp = TimestampRegex.Replace(strippedDuration, "TIMESTAMP"); - var strippedTimestampOffset = TimestampOffsetRegex.Replace(strippedTimestamp, "OFFSET"); - return strippedTimestampOffset; - })); - } - } -} diff --git a/src/Logging/Logging.Testing/test/LoggedTestXunitTests.cs b/src/Logging/Logging.Testing/test/LoggedTestXunitTests.cs deleted file mode 100644 index 61d7802508a..00000000000 --- a/src/Logging/Logging.Testing/test/LoggedTestXunitTests.cs +++ /dev/null @@ -1,193 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -using System.Linq; -using System.Reflection; -using Microsoft.AspNetCore.Testing; -using Microsoft.Extensions.DependencyInjection; -using Xunit; -using Xunit.Abstractions; - -namespace Microsoft.Extensions.Logging.Testing.Tests -{ - [LogLevel(LogLevel.Debug)] - [ShortClassName] - public class LoggedTestXunitTests : TestLoggedTest - { - private readonly ITestOutputHelper _output; - - public LoggedTestXunitTests(ITestOutputHelper output) - { - _output = output; - } - - [Fact] - public void LoggedFactInitializesLoggedTestProperties() - { - Assert.NotNull(Logger); - Assert.NotNull(LoggerFactory); - Assert.NotNull(TestSink); - Assert.NotNull(TestOutputHelper); - } - - [Theory] - [InlineData("Hello world")] - public void LoggedTheoryInitializesLoggedTestProperties(string argument) - { - Assert.NotNull(Logger); - Assert.NotNull(LoggerFactory); - Assert.NotNull(TestSink); - Assert.NotNull(TestOutputHelper); - // Use the test argument - Assert.NotNull(argument); - } - - [ConditionalFact] - public void ConditionalLoggedFactGetsInitializedLoggerFactory() - { - Assert.NotNull(Logger); - Assert.NotNull(LoggerFactory); - Assert.NotNull(TestSink); - Assert.NotNull(TestOutputHelper); - } - - [ConditionalTheory] - [InlineData("Hello world")] - public void LoggedConditionalTheoryInitializesLoggedTestProperties(string argument) - { - Assert.NotNull(Logger); - Assert.NotNull(LoggerFactory); - Assert.NotNull(TestSink); - Assert.NotNull(TestOutputHelper); - // Use the test argument - Assert.NotNull(argument); - } - - [Fact] - [LogLevel(LogLevel.Information)] - public void LoggedFactFilteredByMethodLogLevel() - { - Logger.LogInformation("Information"); - Logger.LogDebug("Debug"); - - var message = Assert.Single(TestSink.Writes); - Assert.Equal(LogLevel.Information, message.LogLevel); - Assert.Equal("Information", message.Formatter(message.State, null)); - } - - [Fact] - public void LoggedFactFilteredByClassLogLevel() - { - Logger.LogDebug("Debug"); - Logger.LogTrace("Trace"); - - var message = Assert.Single(TestSink.Writes); - Assert.Equal(LogLevel.Debug, message.LogLevel); - Assert.Equal("Debug", message.Formatter(message.State, null)); - } - - [Theory] - [InlineData("Hello world")] - [LogLevel(LogLevel.Information)] - public void LoggedTheoryFilteredByLogLevel(string argument) - { - Logger.LogInformation("Information"); - Logger.LogDebug("Debug"); - - var message = Assert.Single(TestSink.Writes); - Assert.Equal(LogLevel.Information, message.LogLevel); - Assert.Equal("Information", message.Formatter(message.State, null)); - - // Use the test argument - Assert.NotNull(argument); - } - - [Fact] - public void AddTestLoggingUpdatedWhenLoggerFactoryIsSet() - { - var loggerFactory = new LoggerFactory(); - var serviceCollection = new ServiceCollection(); - - LoggerFactory = loggerFactory; - AddTestLogging(serviceCollection); - - Assert.Same(loggerFactory, serviceCollection.BuildServiceProvider().GetRequiredService()); - } - - [ConditionalTheory] - [EnvironmentVariableSkipCondition("ASPNETCORE_TEST_LOG_DIR", "")] // The test name is only generated when logging is enabled via the environment variable - [InlineData(null)] - public void LoggedTheoryNullArgumentsAreEscaped(string argument) - { - Assert.NotNull(LoggerFactory); - Assert.Equal($"{nameof(LoggedTheoryNullArgumentsAreEscaped)}_null", ResolvedTestMethodName); - // Use the test argument - Assert.Null(argument); - } - - [Fact] - public void AdditionalSetupInvoked() - { - Assert.True(SetupInvoked); - } - - [Fact] - public void MessageWrittenEventInvoked() - { - WriteContext context = null; - TestSink.MessageLogged += ctx => context = ctx; - Logger.LogInformation("Information"); - Assert.Equal(TestSink.Writes.Single(), context); - } - - [Fact] - public void ScopeStartedEventInvoked() - { - BeginScopeContext context = null; - TestSink.ScopeStarted += ctx => context = ctx; - using (Logger.BeginScope("Scope")) {} - Assert.Equal(TestSink.Scopes.Single(), context); - } - } - - public class LoggedTestXunitLogLevelTests : LoggedTest - { - [Fact] - public void LoggedFactFilteredByAssemblyLogLevel() - { - Logger.LogTrace("Trace"); - - var message = Assert.Single(TestSink.Writes); - Assert.Equal(LogLevel.Trace, message.LogLevel); - Assert.Equal("Trace", message.Formatter(message.State, null)); - } - } - - public class LoggedTestXunitInitializationTests : TestLoggedTest - { - [Fact] - public void ITestOutputHelperInitializedByDefault() - { - Assert.True(ITestOutputHelperIsInitialized); - } - } - - public class TestLoggedTest : LoggedTest - { - public bool SetupInvoked { get; private set; } = false; - public bool ITestOutputHelperIsInitialized { get; private set; } = false; - - public override void Initialize(TestContext context, MethodInfo methodInfo, object[] testMethodArguments, ITestOutputHelper testOutputHelper) - { - base.Initialize(context, methodInfo, testMethodArguments, testOutputHelper); - - try - { - TestOutputHelper.WriteLine("Test"); - ITestOutputHelperIsInitialized = true; - } catch { } - SetupInvoked = true; - } - } -} diff --git a/src/Logging/Logging.Testing/test/Microsoft.Extensions.Logging.Testing.Tests.csproj b/src/Logging/Logging.Testing/test/Microsoft.Extensions.Logging.Testing.Tests.csproj index 7b478d5ce9f..4ec80710b7c 100644 --- a/src/Logging/Logging.Testing/test/Microsoft.Extensions.Logging.Testing.Tests.csproj +++ b/src/Logging/Logging.Testing/test/Microsoft.Extensions.Logging.Testing.Tests.csproj @@ -1,6 +1,4 @@  - - $(DefaultNetCoreTargetFramework);net472