Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
4 changes: 4 additions & 0 deletions src/Microsoft.Android.Build.BaseTasks/AndroidAsyncTask.cs
Original file line number Diff line number Diff line change
Expand Up @@ -46,5 +46,9 @@ public virtual bool RunTask ()
/// * RunTaskAsync is already on a background thread
/// </summary>
public virtual System.Threading.Tasks.Task RunTaskAsync () => System.Threading.Tasks.Task.CompletedTask;

protected (object, string) ProjectSpecificTaskObjectKey (object key){
return (key, WorkingDirectory);
}
}
}
12 changes: 12 additions & 0 deletions src/Microsoft.Android.Build.BaseTasks/AndroidTask.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// https://github.com/xamarin/xamarin-android/blob/9fca138604c53989e1cff7fc0c2e939583b4da28/src/Xamarin.Android.Build.Tasks/Tasks/AndroidTask.cs#L10

using System;
using System.IO;
using Microsoft.Build.Utilities;

namespace Microsoft.Android.Build.Tasks
Expand All @@ -11,6 +12,13 @@ public abstract class AndroidTask : Task
{
public abstract string TaskPrefix { get; }

protected string WorkingDirectory { get; private set; }

public AndroidTask ()
{
WorkingDirectory = Directory.GetCurrentDirectory();
}

public override bool Execute ()
{
try {
Expand All @@ -22,5 +30,9 @@ public override bool Execute ()
}

public abstract bool RunTask ();

protected object ProjectSpecificTaskObjectKey (object key){
return (key, WorkingDirectory);
}
}
}
100 changes: 100 additions & 0 deletions tests/Microsoft.Android.Build.BaseTasks-Tests/AndroidToolTaskTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
using System.IO;
using System.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.Android.Build.BaseTasks.Tests.Utilities;
using Microsoft.Android.Build.Tasks;
using NUnit.Framework;
using Microsoft.Build.Framework;
using Xamarin.Build;

namespace Microsoft.Android.Build.BaseTasks.Tests
{
[TestFixture]
public class AndroidToolTaskTests
{
public class MyAndroidTask : AndroidTask {
public override string TaskPrefix {get;} = "MAT";
public string Key { get; set; }
public string Value { get; set; }
public bool ProjectSpecific { get; set; } = false;
public override bool RunTask ()
{
var key = ProjectSpecific ? ProjectSpecificTaskObjectKey (Key) : Key;
BuildEngine4.RegisterTaskObjectAssemblyLocal (key, Value, RegisteredTaskObjectLifetime.Build);
return true;
}
}

public class MyOtherAndroidTask : AndroidTask {
public override string TaskPrefix {get;} = "MOAT";
public string Key { get; set; }
public bool ProjectSpecific { get; set; } = false;

[Output]
public string Value { get; set; }
public override bool RunTask ()
{
var key = ProjectSpecific ? ProjectSpecificTaskObjectKey (Key) : Key;
Value = BuildEngine4.GetRegisteredTaskObjectAssemblyLocal<string> (key, RegisteredTaskObjectLifetime.Build);
return true;
}
}

[Test]
[TestCase (true, true, true)]
[TestCase (false, false, true)]
[TestCase (true, false, false)]
[TestCase (false, true, false)]
public void TestRegisterTaskObjectCanRetrieveCorrectItem (bool projectSpecificA, bool projectSpecificB, bool expectedResult)
{
var engine = new MockBuildEngine (TestContext.Out) {
};
var task = new MyAndroidTask () {
BuildEngine = engine,
Key = "Foo",
Value = "Foo",
ProjectSpecific = projectSpecificA,
};
task.Execute ();
var task2 = new MyOtherAndroidTask () {
BuildEngine = engine,
Key = "Foo",
ProjectSpecific = projectSpecificB,
};
task2.Execute ();
Assert.AreEqual (expectedResult, string.Compare (task2.Value, task.Value, ignoreCase: true) == 0);
}

[Test]
[TestCase (true, true, false)]
[TestCase (false, false, true)]
[TestCase (true, false, false)]
[TestCase (false, true, false)]
public void TestRegisterTaskObjectFailsWhenDirectoryChanges (bool projectSpecificA, bool projectSpecificB, bool expectedResult)
{
var engine = new MockBuildEngine (TestContext.Out) {
};
MyAndroidTask task;
var currentDir = Directory.GetCurrentDirectory ();
Directory.SetCurrentDirectory (Path.Combine (currentDir, ".."));
try {
task = new MyAndroidTask () {
BuildEngine = engine,
Key = "Foo",
Value = "Foo",
ProjectSpecific = projectSpecificA,
};
} finally {
Directory.SetCurrentDirectory (currentDir);
}
task.Execute ();
var task2 = new MyOtherAndroidTask () {
BuildEngine = engine,
Key = "Foo",
ProjectSpecific = projectSpecificB,
};
task2.Execute ();
Assert.AreEqual (expectedResult, string.Compare (task2.Value, task.Value, ignoreCase: true) == 0);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using Microsoft.Build.Framework;

namespace Microsoft.Android.Build.BaseTasks.Tests.Utilities {
public class MockBuildEngine : IBuildEngine, IBuildEngine2, IBuildEngine3, IBuildEngine4 {
public MockBuildEngine (TextWriter output, IList<BuildErrorEventArgs> errors = null, IList<BuildWarningEventArgs> warnings = null, IList<BuildMessageEventArgs> messages = null, IList<CustomBuildEventArgs> customEvents = null)
{
this.Output = output;
this.Errors = errors;
this.Warnings = warnings;
this.Messages = messages;
this.CustomEvents = customEvents;
}

private TextWriter Output { get; }

private IList<BuildErrorEventArgs> Errors { get; }

private IList<BuildWarningEventArgs> Warnings { get; }

private IList<BuildMessageEventArgs> Messages { get; }

private IList<CustomBuildEventArgs> CustomEvents { get; }

int IBuildEngine.ColumnNumberOfTaskNode => -1;

bool IBuildEngine.ContinueOnError => false;

int IBuildEngine.LineNumberOfTaskNode => -1;

string IBuildEngine.ProjectFileOfTaskNode => "this.xml";

bool IBuildEngine2.IsRunningMultipleNodes => false;

bool IBuildEngine.BuildProjectFile (string projectFileName, string [] targetNames, IDictionary globalProperties, IDictionary targetOutputs) => true;

void IBuildEngine.LogCustomEvent (CustomBuildEventArgs e)
{
this.Output.WriteLine ($"Custom: {e.Message}");
if (CustomEvents != null)
CustomEvents.Add (e);
}

void IBuildEngine.LogErrorEvent (BuildErrorEventArgs e)
{
this.Output.WriteLine ($"Error: {e.Message}");
if (Errors != null)
Errors.Add (e);
}

void IBuildEngine.LogMessageEvent (BuildMessageEventArgs e)
{
this.Output.WriteLine ($"Message: {e.Message}");
if (Messages != null)
Messages.Add (e);
}

void IBuildEngine.LogWarningEvent (BuildWarningEventArgs e)
{
this.Output.WriteLine ($"Warning: {e.Message}");
if (Warnings != null)
Warnings.Add (e);
}

private Dictionary<object, object> Tasks = new Dictionary<object, object> ();

void IBuildEngine4.RegisterTaskObject (object key, object obj, RegisteredTaskObjectLifetime lifetime, bool allowEarlyCollection)
{
Tasks.Add (key, obj);
}

object IBuildEngine4.GetRegisteredTaskObject (object key, RegisteredTaskObjectLifetime lifetime)
{
object obj = null;
Tasks.TryGetValue (key, out obj);
return obj;
}

object IBuildEngine4.UnregisterTaskObject (object key, RegisteredTaskObjectLifetime lifetime)
{
var obj = Tasks [key];
Tasks.Remove (key);
return obj;
}

BuildEngineResult IBuildEngine3.BuildProjectFilesInParallel (string [] projectFileNames, string [] targetNames, IDictionary [] globalProperties, IList<string> [] removeGlobalProperties, string [] toolsVersion, bool returnTargetOutputs)
{
throw new NotImplementedException ();
}

void IBuildEngine3.Yield () { }

void IBuildEngine3.Reacquire () { }

bool IBuildEngine2.BuildProjectFile (string projectFileName, string [] targetNames, IDictionary globalProperties, IDictionary targetOutputs, string toolsVersion) => true;

bool IBuildEngine2.BuildProjectFilesInParallel (string [] projectFileNames, string [] targetNames, IDictionary [] globalProperties, IDictionary [] targetOutputsPerProject, string [] toolsVersion, bool useResultsCache, bool unloadProjectsOnCompletion) => true;
}
}