Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Permit a task to disable MSB4181 Fixes #5203 #5207

Merged
merged 4 commits into from
Apr 28, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,10 @@ public partial interface IBuildEngine6 : Microsoft.Build.Framework.IBuildEngine,
{
System.Collections.Generic.IReadOnlyDictionary<string, string> GetGlobalProperties();
}
public partial interface IBuildEngine7 : Microsoft.Build.Framework.IBuildEngine, Microsoft.Build.Framework.IBuildEngine2, Microsoft.Build.Framework.IBuildEngine3, Microsoft.Build.Framework.IBuildEngine4, Microsoft.Build.Framework.IBuildEngine5, Microsoft.Build.Framework.IBuildEngine6
{
bool AllowFailureWithoutError { get; set; }
}
public partial interface ICancelableTask : Microsoft.Build.Framework.ITask
{
void Cancel();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,10 @@ public partial interface IBuildEngine6 : Microsoft.Build.Framework.IBuildEngine,
{
System.Collections.Generic.IReadOnlyDictionary<string, string> GetGlobalProperties();
}
public partial interface IBuildEngine7 : Microsoft.Build.Framework.IBuildEngine, Microsoft.Build.Framework.IBuildEngine2, Microsoft.Build.Framework.IBuildEngine3, Microsoft.Build.Framework.IBuildEngine4, Microsoft.Build.Framework.IBuildEngine5, Microsoft.Build.Framework.IBuildEngine6
{
bool AllowFailureWithoutError { get; set; }
}
public partial interface ICancelableTask : Microsoft.Build.Framework.ITask
{
void Cancel();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -352,6 +352,7 @@ protected Task(System.Resources.ResourceManager taskResources, string helpKeywor
public Microsoft.Build.Framework.IBuildEngine4 BuildEngine4 { get { throw null; } }
public Microsoft.Build.Framework.IBuildEngine5 BuildEngine5 { get { throw null; } }
public Microsoft.Build.Framework.IBuildEngine6 BuildEngine6 { get { throw null; } }
public Microsoft.Build.Framework.IBuildEngine7 BuildEngine7 { get { throw null; } }
protected string HelpKeywordPrefix { get { throw null; } set { } }
public Microsoft.Build.Framework.ITaskHost HostObject { get { throw null; } set { } }
public Microsoft.Build.Utilities.TaskLoggingHelper Log { get { throw null; } }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,7 @@ protected Task(System.Resources.ResourceManager taskResources, string helpKeywor
public Microsoft.Build.Framework.IBuildEngine4 BuildEngine4 { get { throw null; } }
public Microsoft.Build.Framework.IBuildEngine5 BuildEngine5 { get { throw null; } }
public Microsoft.Build.Framework.IBuildEngine6 BuildEngine6 { get { throw null; } }
public Microsoft.Build.Framework.IBuildEngine7 BuildEngine7 { get { throw null; } }
protected string HelpKeywordPrefix { get { throw null; } set { } }
public Microsoft.Build.Framework.ITaskHost HostObject { get { throw null; } set { } }
public Microsoft.Build.Utilities.TaskLoggingHelper Log { get { throw null; } }
Expand Down
1 change: 1 addition & 0 deletions ref/Microsoft.Build/net/Microsoft.Build.cs
Original file line number Diff line number Diff line change
Expand Up @@ -967,6 +967,7 @@ public partial class BuildParameters
{
public BuildParameters() { }
public BuildParameters(Microsoft.Build.Evaluation.ProjectCollection projectCollection) { }
public bool AllowFailureWithoutError { get { throw null; } set { } }
public System.Collections.Generic.IDictionary<string, string> BuildProcessEnvironment { get { throw null; } }
public System.Threading.ThreadPriority BuildThreadPriority { get { throw null; } set { } }
public System.Globalization.CultureInfo Culture { get { throw null; } set { } }
Expand Down
1 change: 1 addition & 0 deletions ref/Microsoft.Build/netstandard/Microsoft.Build.cs
Original file line number Diff line number Diff line change
Expand Up @@ -963,6 +963,7 @@ public partial class BuildParameters
{
public BuildParameters() { }
public BuildParameters(Microsoft.Build.Evaluation.ProjectCollection projectCollection) { }
public bool AllowFailureWithoutError { get { throw null; } set { } }
public System.Collections.Generic.IDictionary<string, string> BuildProcessEnvironment { get { throw null; } }
public System.Globalization.CultureInfo Culture { get { throw null; } set { } }
public string DefaultToolsVersion { get { throw null; } set { } }
Expand Down
2 changes: 1 addition & 1 deletion src/Build.UnitTests/BackEnd/BuildResult_Tests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@
using Microsoft.Build.Framework;
using Microsoft.Build.Shared;
using Microsoft.Build.Unittest;
using Shouldly;
using Xunit;

using TaskItem = Microsoft.Build.Execution.ProjectItemInstance.TaskItem;

namespace Microsoft.Build.UnitTests.BackEnd
Expand Down
20 changes: 20 additions & 0 deletions src/Build.UnitTests/BackEnd/FailingTask.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

using Microsoft.Build.Framework;
using Microsoft.Build.Utilities;

namespace Microsoft.Build.UnitTests
{
public class FailingTask : Task
{
public override bool Execute()
{
BuildEngine.GetType().GetProperty("AllowFailureWithoutError").SetValue(BuildEngine, EnableDefaultFailure);
return false;
}

[Required]
public bool EnableDefaultFailure { get; set; }
}
}
49 changes: 37 additions & 12 deletions src/Build.UnitTests/BackEnd/LoggingContext_Tests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,10 @@
using Microsoft.Build.BackEnd;
using Microsoft.Build.BackEnd.Logging;
using Microsoft.Build.Shared;
using Shouldly;
using System;
using Xunit;
using Xunit.Abstractions;

namespace Microsoft.Build.UnitTests.BackEnd
{
Expand All @@ -14,29 +16,36 @@ namespace Microsoft.Build.UnitTests.BackEnd
/// </summary>
public class LoggingContext_Tests
{
private readonly ITestOutputHelper _output;

public LoggingContext_Tests(ITestOutputHelper outputHelper)
{
_output = outputHelper;
}

/// <summary>
/// A few simple tests for NodeLoggingContexts.
/// </summary>
[Fact]
public void CreateValidNodeLoggingContexts()
{
NodeLoggingContext context = new NodeLoggingContext(new MockLoggingService(), 1, true);
Assert.True(context.IsInProcNode);
Assert.True(context.IsValid);
NodeLoggingContext context = new NodeLoggingContext(new MockLoggingService(_output.WriteLine), 1, true);
context.IsInProcNode.ShouldBeTrue();
context.IsValid.ShouldBeTrue();

context.LogBuildFinished(true);
Assert.False(context.IsValid);
context.IsValid.ShouldBeFalse();

Assert.Equal(1, context.BuildEventContext.NodeId);
context.BuildEventContext.NodeId.ShouldBe(1);

NodeLoggingContext context2 = new NodeLoggingContext(new MockLoggingService(), 2, false);
Assert.False(context2.IsInProcNode);
Assert.True(context2.IsValid);
NodeLoggingContext context2 = new NodeLoggingContext(new MockLoggingService(_output.WriteLine), 2, false);
context2.IsInProcNode.ShouldBeFalse();
context2.IsValid.ShouldBeTrue();

context2.LogBuildFinished(true);
Assert.False(context2.IsValid);
context2.IsValid.ShouldBeFalse();

Assert.Equal(2, context2.BuildEventContext.NodeId);
context2.BuildEventContext.NodeId.ShouldBe(2);
}

/// <summary>
Expand All @@ -49,9 +58,25 @@ public void InvalidNodeIdOnNodeLoggingContext()
{
Assert.Throws<InternalErrorException>(() =>
{
NodeLoggingContext context = new NodeLoggingContext(new MockLoggingService(), -2, true);
_ = new NodeLoggingContext(new MockLoggingService(), -2, true);
}
);
}

[Fact]
public void HasLoggedErrors()
{
NodeLoggingContext context = new NodeLoggingContext(new MockLoggingService(_output.WriteLine), 1, true);
context.HasLoggedErrors.ShouldBeFalse();

context.LogCommentFromText(Framework.MessageImportance.High, "Test message");
context.HasLoggedErrors.ShouldBeFalse();

context.LogWarningFromText(null, null, null, null, "Test warning");
context.HasLoggedErrors.ShouldBeFalse();

context.LogErrorFromText(null, null, null, null, "Test error");
context.HasLoggedErrors.ShouldBeTrue();
}
}
}
}
26 changes: 26 additions & 0 deletions src/Build.UnitTests/BackEnd/OnError_Tests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@
using System.Xml;
using InvalidProjectFileException = Microsoft.Build.Exceptions.InvalidProjectFileException;
using Xunit;
using System.Reflection;
using Shouldly;
using System.Linq;

namespace Microsoft.Build.UnitTests.BackEnd
{
Expand Down Expand Up @@ -559,6 +562,29 @@ public void OutOfOrderOnError()
);
}

[Theory]
[InlineData(false)]
[InlineData(true)]
public void ErrorWhenTaskFailsWithoutLoggingErrorEscapeHatch(bool emitError)
{
MockLogger logger = ObjectModelHelpers.BuildProjectExpectFailure($@"
<Project>
<UsingTask TaskName=""FailingTask"" AssemblyFile=""{Assembly.GetExecutingAssembly().Location}"" />
<Target Name=""MyTarget"">
<FailingTask EnableDefaultFailure=""{emitError}"" />
</Target>
</Project>");
if (emitError)
{
logger.ErrorCount.ShouldBe(1);
logger.Errors.First().Code.ShouldBe("MSB4181");
}
else
{
logger.ErrorCount.ShouldBe(0);
}
}

#region Postbuild
/*
* Method: PostBuildBasic
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

using Microsoft.Build.BackEnd.Logging;
using Microsoft.Build.Utilities;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Microsoft.Build.UnitTests
{
/// <summary>
/// This task was created for https://github.com/microsoft/msbuild/issues/2036
/// </summary>
public class ReturnFailureWithoutLoggingErrorTask : Task
{
/// <summary>
/// Intentionally return false without logging an error to test proper error catching.
/// </summary>
/// <returns></returns>
public override bool Execute()
{
return false;
}
}
}
119 changes: 117 additions & 2 deletions src/Build.UnitTests/WarningsAsMessagesAndErrors_Tests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@
using System.Linq;
using Microsoft.Build.Framework;
using Microsoft.Build.UnitTests;
using Shouldly;
using Xunit;
using Xunit.Abstractions;

namespace Microsoft.Build.Engine.UnitTests
{
Expand All @@ -13,6 +15,13 @@ public sealed class WarningsAsMessagesAndErrorsTests
private const string ExpectedEventMessage = "03767942CDB147B98D0ECDBDE1436DA3";
private const string ExpectedEventCode = "0BF68998";

ITestOutputHelper _output;

public WarningsAsMessagesAndErrorsTests(ITestOutputHelper output)
{
_output = output;
}

[Fact]
public void TreatAllWarningsAsErrors()
{
Expand All @@ -29,7 +38,7 @@ public void TreatAllWarningsAsErrors()
[Fact]
public void TreatWarningsAsErrorsWhenBuildingSameProjectMultipleTimes()
{
using (TestEnvironment testEnvironment = TestEnvironment.Create())
using (TestEnvironment testEnvironment = TestEnvironment.Create(_output))
{
TransientTestProjectWithFiles project2 = testEnvironment.CreateTestProjectWithFiles($@"
<Project xmlns=""msbuildnamespace"">
Expand Down Expand Up @@ -123,7 +132,7 @@ public void TreatWarningsAsMessagesWhenSpecified()
[Fact]
public void TreatWarningsAsMessagesWhenBuildingSameProjectMultipleTimes()
{
using (TestEnvironment testEnvironment = TestEnvironment.Create())
using (TestEnvironment testEnvironment = TestEnvironment.Create(_output))
{
TransientTestProjectWithFiles project2 = testEnvironment.CreateTestProjectWithFiles($@"
<Project xmlns=""msbuildnamespace"">
Expand Down Expand Up @@ -263,5 +272,111 @@ private string GetTestProject(bool? treatAllWarningsAsErrors = null, string warn
</Target>
</Project>";
}

[Fact]
public void TaskReturnsFailureButDoesNotLogError_ShouldCauseBuildFailure()
{

using (TestEnvironment env = TestEnvironment.Create(_output))
{
TransientTestProjectWithFiles proj = env.CreateTestProjectWithFiles($@"
<Project>
<UsingTask TaskName = ""ReturnFailureWithoutLoggingErrorTask"" AssemblyName=""Microsoft.Build.Engine.UnitTests""/>
<Target Name='Build'>
<ReturnFailureWithoutLoggingErrorTask/>
</Target>
</Project>");

MockLogger logger = proj.BuildProjectExpectFailure();

logger.AssertLogContains("MSB4181");
}
}

[Fact]
public void TaskReturnsFailureButDoesNotLogError_ContinueOnError_WarnAndContinue()
{

using (TestEnvironment env = TestEnvironment.Create(_output))
{
TransientTestProjectWithFiles proj = env.CreateTestProjectWithFiles($@"
<Project>
<UsingTask TaskName = ""ReturnFailureWithoutLoggingErrorTask"" AssemblyName=""Microsoft.Build.Engine.UnitTests""/>
<Target Name='Build'>
<ReturnFailureWithoutLoggingErrorTask
ContinueOnError=""WarnAndContinue""/>
</Target>
</Project>");

MockLogger logger = proj.BuildProjectExpectSuccess();

logger.WarningCount.ShouldBe(1);

logger.AssertLogContains("MSB4181");
}
}

[Fact]
public void TaskReturnsFailureButDoesNotLogError_ContinueOnError_True()
{

using (TestEnvironment env = TestEnvironment.Create(_output))
{
TransientTestProjectWithFiles proj = env.CreateTestProjectWithFiles($@"
<Project>
<UsingTask TaskName = ""ReturnFailureWithoutLoggingErrorTask"" AssemblyName=""Microsoft.Build.Engine.UnitTests""/>
<Target Name='Build'>
<ReturnFailureWithoutLoggingErrorTask
ContinueOnError=""true""/>
</Target>
</Project>");

MockLogger logger = proj.BuildProjectExpectSuccess();

logger.AssertLogContains("MSB4181");
}
}

[Fact]
public void TaskReturnsFailureButDoesNotLogError_ContinueOnError_ErrorAndStop()
{

using (TestEnvironment env = TestEnvironment.Create(_output))
{
TransientTestProjectWithFiles proj = env.CreateTestProjectWithFiles($@"
<Project>
<UsingTask TaskName = ""ReturnFailureWithoutLoggingErrorTask"" AssemblyName=""Microsoft.Build.Engine.UnitTests""/>
<Target Name='Build'>
<ReturnFailureWithoutLoggingErrorTask
ContinueOnError=""ErrorAndStop""/>
</Target>
</Project>");

MockLogger logger = proj.BuildProjectExpectFailure();

logger.AssertLogContains("MSB4181");
}
}

[Fact]
public void TaskReturnsFailureButDoesNotLogError_ContinueOnError_False()
{

using (TestEnvironment env = TestEnvironment.Create(_output))
{
TransientTestProjectWithFiles proj = env.CreateTestProjectWithFiles($@"
<Project>
<UsingTask TaskName = ""ReturnFailureWithoutLoggingErrorTask"" AssemblyName=""Microsoft.Build.Engine.UnitTests""/>
<Target Name='Build'>
<ReturnFailureWithoutLoggingErrorTask
ContinueOnError=""false""/>
</Target>
</Project>");

MockLogger logger = proj.BuildProjectExpectFailure();

logger.AssertLogContains("MSB4181");
}
}
}
}
Loading