|
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using Microsoft.Build.BackEnd.Logging;
using Microsoft.Build.Evaluation;
using Microsoft.Build.Execution;
using Microsoft.Build.Framework;
using Microsoft.Build.Shared;
using Microsoft.Build.UnitTests;
using Shouldly;
using Xunit;
using Xunit.Abstractions;
using Xunit.NetCore.Extensions;
using static Microsoft.Build.UnitTests.ObjectModelHelpers;
#nullable disable
namespace Microsoft.Build.Engine.UnitTests.BackEnd
{
public class BuildManager_Logging_Tests : IDisposable
{
private string _mainProject = @"
<Project>
<Target Name=`MainTarget`>
<MSBuild Projects=`{0}` Targets=`ChildTarget` />
</Target>
</Project>";
private string _childProjectWithCustomBuildEvent = $@"
<Project>
<UsingTask TaskName=""CustomBuildEventTask"" AssemblyFile=""{Assembly.GetExecutingAssembly().Location}"" />
<Target Name=`ChildTarget`>
<CustomBuildEventTask />
</Target>
</Project>";
/// <summary>
/// The mock logger for testing.
/// </summary>
private readonly MockLogger _logger;
/// <summary>
/// The standard build manager for each test.
/// </summary>
private readonly BuildManager _buildManager;
/// <summary>
/// The project collection used.
/// </summary>
private readonly ProjectCollection _projectCollection;
private readonly TestEnvironment _env;
private readonly ITestOutputHelper _output;
/// <summary>
/// SetUp
/// </summary>
public BuildManager_Logging_Tests(ITestOutputHelper output)
{
_output = output;
// Ensure that any previous tests which may have been using the default BuildManager do not conflict with us.
BuildManager.DefaultBuildManager.Dispose();
_logger = new MockLogger(output);
_buildManager = new BuildManager();
_projectCollection = new ProjectCollection();
_env = TestEnvironment.Create(output);
}
[DotNetOnlyTheory]
[InlineData("1", true)]
// [InlineData("0", true)] <-- explicitly opting out on core will lead to node crash (as documented)
[InlineData(null, true)]
public void Build_WithCustomBuildArgs_NetCore(string envVariableValue, bool isWarningExpected)
=> TestCustomEventWarning<BuildErrorEventArgs>(envVariableValue, isWarningExpected);
[WindowsFullFrameworkOnlyTheory]
[InlineData("1", true)]
[InlineData("0", false)]
[InlineData(null, true)]
public void Build_WithCustomBuildArgs_Framework(string envVariableValue, bool isWarningExpected) =>
TestCustomEventWarning<BuildWarningEventArgs>(envVariableValue, isWarningExpected);
private void TestCustomEventWarning<T>(string envVariableValue, bool isWarningExpected) where T : LazyFormattedBuildEventArgs
{
var testFiles = _env.CreateTestProjectWithFiles(string.Empty, new[] { "main", "child1" }, string.Empty);
ILoggingService service = LoggingService.CreateLoggingService(LoggerMode.Synchronous, 1);
service.RegisterLogger(_logger);
_env.SetEnvironmentVariable("MSBUILDCUSTOMBUILDEVENTWARNING", envVariableValue);
_env.SetEnvironmentVariable("MSBUILDNOINPROCNODE", "1");
_buildManager.BeginBuild(BuildParameters);
try
{
var child1ProjectPath = testFiles.CreatedFiles[1];
var cleanedUpChildContents = CleanupFileContents(_childProjectWithCustomBuildEvent);
File.WriteAllText(child1ProjectPath, cleanedUpChildContents);
var mainProjectPath = testFiles.CreatedFiles[0];
var cleanedUpMainContents = CleanupFileContents(string.Format(_mainProject, child1ProjectPath));
File.WriteAllText(mainProjectPath, cleanedUpMainContents);
var buildRequestData = new BuildRequestData(
mainProjectPath,
new Dictionary<string, string>(),
MSBuildConstants.CurrentToolsVersion,
new[] { "MainTarget" },
null);
var submission = _buildManager.PendBuildRequest(buildRequestData);
var result = submission.Execute();
var allEvents = _logger.AllBuildEvents;
if (isWarningExpected)
{
allEvents.OfType<T>().ShouldHaveSingleItem();
allEvents.First(x => x is T).Message.ShouldContain(
string.Format(ResourceUtilities.GetResourceString("DeprecatedEventSerialization"),
"MyCustomBuildEventArgs"));
}
else
{
allEvents.OfType<T>().ShouldBeEmpty();
}
}
finally
{
_buildManager.EndBuild();
}
}
private BuildParameters BuildParameters => new BuildParameters(_projectCollection)
{
DisableInProcNode = true,
EnableNodeReuse = false,
Loggers = new ILogger[] { _logger }
};
/// <summary>
/// TearDown
/// </summary>
public void Dispose()
{
try
{
_buildManager.Dispose();
_projectCollection.Dispose();
}
finally
{
_env.Dispose();
}
}
}
}
|