From 5cfb9f6b7b7f06b59b3728f03285404fff191bb8 Mon Sep 17 00:00:00 2001 From: Ladi Prosek Date: Thu, 29 Apr 2021 12:04:01 +0200 Subject: [PATCH] Add unit tests --- .../BackEnd/LoggingService_Tests.cs | 88 +++++++++++++++++++ src/MSBuild.UnitTests/XMake_Tests.cs | 62 +++++++++++++ 2 files changed, 150 insertions(+) diff --git a/src/Build.UnitTests/BackEnd/LoggingService_Tests.cs b/src/Build.UnitTests/BackEnd/LoggingService_Tests.cs index 9a485cb0d49..4d84c33b60f 100644 --- a/src/Build.UnitTests/BackEnd/LoggingService_Tests.cs +++ b/src/Build.UnitTests/BackEnd/LoggingService_Tests.cs @@ -665,6 +665,11 @@ public void Properties() Assert.Equal(1, loggingService.MaxCPUCount); loggingService.MaxCPUCount = 5; Assert.Equal(5, loggingService.MaxCPUCount); + + // Test MinimumRequiredMessageImportance + Assert.Equal(MessageImportance.Low, loggingService.MinimumRequiredMessageImportance); + loggingService.RegisterLogger(new ConsoleLogger(LoggerVerbosity.Normal)); + Assert.Equal(MessageImportance.Normal, loggingService.MinimumRequiredMessageImportance); } #endregion @@ -718,6 +723,8 @@ public void LoggingPacketReceived() #endregion + #region WarningsAsErrors Tests + private static readonly BuildWarningEventArgs BuildWarningEventForTreatAsErrorOrMessageTests = new BuildWarningEventArgs("subcategory", "C94A41A90FFB4EF592BF98BA59BEE8AF", "file", 1, 2, 3, 4, "message", "helpKeyword", "senderName"); /// @@ -1000,6 +1007,76 @@ private MockLogger GetLoggedEventsWithWarningsAsErrorsOrMessages( return logger; } + #endregion + + #region MinimumRequiredMessageImportance Tests + + [Fact] + public void ImportanceReflectsConsoleLoggerVerbosity() + { + _initializedService.RegisterLogger(new ConsoleLogger(LoggerVerbosity.Quiet)); + _initializedService.MinimumRequiredMessageImportance.ShouldBe(MessageImportance.High - 1); + _initializedService.RegisterLogger(new ConsoleLogger(LoggerVerbosity.Minimal)); + _initializedService.MinimumRequiredMessageImportance.ShouldBe(MessageImportance.High); + _initializedService.RegisterLogger(new ConsoleLogger(LoggerVerbosity.Normal)); + _initializedService.MinimumRequiredMessageImportance.ShouldBe(MessageImportance.Normal); + _initializedService.RegisterLogger(new ConsoleLogger(LoggerVerbosity.Detailed)); + _initializedService.MinimumRequiredMessageImportance.ShouldBe(MessageImportance.Low); + _initializedService.RegisterLogger(new ConsoleLogger(LoggerVerbosity.Diagnostic)); + _initializedService.MinimumRequiredMessageImportance.ShouldBe(MessageImportance.Low); + } + + [Fact] + public void ImportanceReflectsConfigurableForwardingLoggerVerbosity() + { + _initializedService.RegisterLogger(CreateConfigurableForwardingLogger(LoggerVerbosity.Quiet)); + _initializedService.MinimumRequiredMessageImportance.ShouldBe(MessageImportance.High - 1); + _initializedService.RegisterLogger(CreateConfigurableForwardingLogger(LoggerVerbosity.Minimal)); + _initializedService.MinimumRequiredMessageImportance.ShouldBe(MessageImportance.High); + _initializedService.RegisterLogger(CreateConfigurableForwardingLogger(LoggerVerbosity.Normal)); + _initializedService.MinimumRequiredMessageImportance.ShouldBe(MessageImportance.Normal); + _initializedService.RegisterLogger(CreateConfigurableForwardingLogger(LoggerVerbosity.Detailed)); + _initializedService.MinimumRequiredMessageImportance.ShouldBe(MessageImportance.Low); + _initializedService.RegisterLogger(CreateConfigurableForwardingLogger(LoggerVerbosity.Diagnostic)); + _initializedService.MinimumRequiredMessageImportance.ShouldBe(MessageImportance.Low); + } + + [Fact] + public void ImportanceReflectsCentralForwardingLoggerVerbosity() + { + MockHost mockHost = new MockHost(); + ILoggingService node1LoggingService = LoggingService.CreateLoggingService(LoggerMode.Synchronous, 1); + ((IBuildComponent)node1LoggingService).InitializeComponent(mockHost); + ILoggingService node2LoggingService = LoggingService.CreateLoggingService(LoggerMode.Synchronous, 2); + ((IBuildComponent)node2LoggingService).InitializeComponent(mockHost); + + // CentralForwardingLogger is always registered in in-proc nodes and it does not affect minimum importance. + node1LoggingService.RegisterLogger(CreateConfigurableForwardingLogger(LoggerVerbosity.Minimal)); + node1LoggingService.RegisterLogger(new CentralForwardingLogger()); + node1LoggingService.MinimumRequiredMessageImportance.ShouldBe(MessageImportance.High); + + // CentralForwardingLogger in out-of-proc nodes means that we are forwarding everything and the minimum importance + // is Low regardless of what other loggers are registered. + node2LoggingService.RegisterLogger(CreateConfigurableForwardingLogger(LoggerVerbosity.Minimal)); + node2LoggingService.RegisterLogger(new CentralForwardingLogger()); + node2LoggingService.MinimumRequiredMessageImportance.ShouldBe(MessageImportance.Low); + // Register another ConsoleLogger and verify that minimum importance hasn't changed. + node2LoggingService.RegisterLogger(CreateConfigurableForwardingLogger(LoggerVerbosity.Minimal)); + node2LoggingService.MinimumRequiredMessageImportance.ShouldBe(MessageImportance.Low); + } + + [Fact] + public void ImportanceReflectsUnknownLoggerVerbosity() + { + // Minimum message importance is Low (i.e. we're logging everything) even when all registered loggers have + // Normal verbosity if at least of one them is not on our whitelist. + _initializedService.RegisterLogger(new ConsoleLogger(LoggerVerbosity.Normal)); + _initializedService.RegisterLogger(new MockLogger() { Verbosity = LoggerVerbosity.Normal }); + _initializedService.RegisterLogger(CreateConfigurableForwardingLogger(LoggerVerbosity.Normal)); + _initializedService.MinimumRequiredMessageImportance.ShouldBe(MessageImportance.Low); + } + #endregion + #region PrivateMethods /// @@ -1084,6 +1161,17 @@ private LoggerDescription CreateLoggerDescription(string loggerClassName, string ); return centralLoggerDescrption; } + + /// + /// Creates a new with the given verbosity. + /// + private ConfigurableForwardingLogger CreateConfigurableForwardingLogger(LoggerVerbosity verbosity) + { + return new ConfigurableForwardingLogger() + { + Verbosity = verbosity + }; + } #endregion #region HelperClasses diff --git a/src/MSBuild.UnitTests/XMake_Tests.cs b/src/MSBuild.UnitTests/XMake_Tests.cs index e014f5652e3..baff6bcfd55 100644 --- a/src/MSBuild.UnitTests/XMake_Tests.cs +++ b/src/MSBuild.UnitTests/XMake_Tests.cs @@ -19,6 +19,7 @@ using Shouldly; using System.IO.Compression; using System.Reflection; +using Microsoft.Build.Utilities; namespace Microsoft.Build.UnitTests { @@ -2335,6 +2336,67 @@ public void EndToEndWarnAsErrors() success.ShouldBeFalse(); } + /// + /// Helper task used by to verify . + /// + public class MessageImportanceCheckingTask : Task + { + public int ExpectedMinimumMessageImportance { get; set; } + + public override bool Execute() + { + bool shouldLogHigh = Log.ShouldLogMessage(MessageImportance.High); + bool shouldLogNormal = Log.ShouldLogMessage(MessageImportance.Normal); + bool shouldLogLow = Log.ShouldLogMessage(MessageImportance.Low); + return (MessageImportance)ExpectedMinimumMessageImportance switch + { + MessageImportance.High - 1 => !shouldLogHigh && !shouldLogNormal && !shouldLogLow, + MessageImportance.High => shouldLogHigh && !shouldLogNormal && !shouldLogLow, + MessageImportance.Normal => shouldLogHigh && shouldLogNormal && !shouldLogLow, + MessageImportance.Low => shouldLogHigh && shouldLogNormal && shouldLogLow, + _ => false + }; + } + } + + [Theory] + [InlineData("/v:diagnostic", MessageImportance.Low)] + [InlineData("/v:detailed", MessageImportance.Low)] + [InlineData("/v:normal", MessageImportance.Normal)] + [InlineData("/v:minimal", MessageImportance.High)] + [InlineData("/v:quiet", MessageImportance.High - 1)] + [InlineData("/v:diagnostic /bl", MessageImportance.Low)] + [InlineData("/v:detailed /bl", MessageImportance.Low)] + [InlineData("/v:normal /bl", MessageImportance.Low)] // v:normal but with binary logger so everything must be logged + [InlineData("/v:minimal /bl", MessageImportance.Low)] // v:minimal but with binary logger so everything must be logged + [InlineData("/v:quiet /bl", MessageImportance.Low)] // v:quiet but with binary logger so everything must be logged + public void EndToEndMinimumMessageImportance(string arguments, MessageImportance expectedMinimumMessageImportance) + { + using TestEnvironment testEnvironment = UnitTests.TestEnvironment.Create(); + + string projectContents = ObjectModelHelpers.CleanupFileContents(@" + + + + + + + +"); + + TransientTestProjectWithFiles testProject = testEnvironment.CreateTestProjectWithFiles(projectContents); + + // Build in-proc. + RunnerUtilities.ExecMSBuild($"{arguments} \"{testProject.ProjectFile}\"", out bool success, _output); + success.ShouldBeTrue(); + + // Build out-of-proc to exercise both logging code paths. + testEnvironment.SetEnvironmentVariable("MSBUILDNOINPROCNODE", "1"); + testEnvironment.SetEnvironmentVariable("MSBUILDDISABLENODEREUSE", "1"); + RunnerUtilities.ExecMSBuild($"{arguments} \"{testProject.ProjectFile}\"", out success, _output); + success.ShouldBeTrue(); + } + #if FEATURE_ASSEMBLYLOADCONTEXT /// /// Ensure that tasks get loaded into their own