Skip to content
Open
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
2 changes: 1 addition & 1 deletion Documentation/guides/FastDeploy.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ inner-loop change only re-transfers the files that actually changed.
This document describes how the [`FastDeploy`][task] MSBuild task works: the
stages it runs, the `adb` commands it issues, and the properties that control it.

[task]: ../../src/Xamarin.Android.Build.Debugging.Tasks/Tasks/FastDeploy.cs
[task]: ../../src/Microsoft.Android.Build.Tasks/Tasks/FastDeploy.cs

## MSBuild properties

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,4 +90,13 @@
</EmbeddedResource>
</ItemGroup>

<!-- FastDeploy shares AndroidHelper and its localized XA#### messages with Xamarin.Android.Build.Debugging.Tasks. -->
<ItemGroup>
<Compile Include="..\Xamarin.Android.Build.Debugging.Tasks\Utilities\AndroidHelper.cs" Link="Utilities\AndroidHelper.cs" />
<Compile Include="..\Xamarin.Android.Build.Debugging.Tasks\Properties\Resources.Designer.cs" Link="Properties\DebuggingResources.Designer.cs" />
<EmbeddedResource Include="..\Xamarin.Android.Build.Debugging.Tasks\Properties\Resources*.resx" Link="Properties\Debugging%(Filename)%(Extension)">
<ManifestResourceName>Xamarin.Android.Build.Debugging.Tasks.Properties.%(Filename)</ManifestResourceName>
</EmbeddedResource>
Comment on lines +97 to +99
</ItemGroup>

</Project>
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
#nullable disable
using System;
using System.Collections.Generic;
using System.Linq;
Expand All @@ -6,7 +7,7 @@

using Xamarin.Android.Tools;

namespace Xamarin.Android.Tasks
namespace Microsoft.Android.Tasks
{
public partial class FastDeploy
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
#nullable disable
using System;
using System.Collections.Generic;
using System.IO;
Expand All @@ -8,7 +9,7 @@
using System.Text.Json.Serialization;
using System.Threading.Tasks;

namespace Xamarin.Android.Tasks
namespace Microsoft.Android.Tasks
{
public partial class FastDeploy
{
Expand Down Expand Up @@ -547,7 +548,7 @@ static string GetCanonicalManifestText (ManifestData manifest)
builder.Append (entry.Key).Append ('\t')
.Append (entry.Value.RelativePath).Append ('\t')
.Append (entry.Value.Size).Append ('\t')
.AppendLine (entry.Value.LastWriteTimeUtcTicks.ToString ());
.AppendLine (entry.Value.LastWriteTimeUtcTicks.ToString (System.Globalization.CultureInfo.CurrentCulture));
}
return builder.ToString ();
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
#nullable disable
using System;
using System.IO;
using System.Linq;
using System.Threading.Tasks;

using Xamarin.Android.Build.Debugging.Tasks.Properties;

namespace Xamarin.Android.Tasks
namespace Microsoft.Android.Tasks
{
public partial class FastDeploy
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
#nullable disable
using System;
using System.Collections.Generic;
using System.Diagnostics;
Expand All @@ -10,9 +11,10 @@
using Microsoft.Android.Build.Tasks;
using Microsoft.Build.Framework;
using Xamarin.Android.Build.Debugging.Tasks.Properties;
using Xamarin.Android.Tasks;
using Xamarin.Android.Tools;

namespace Xamarin.Android.Tasks
namespace Microsoft.Android.Tasks
{
public partial class FastDeploy : AsyncTask
{
Expand Down Expand Up @@ -527,8 +529,8 @@ byte [] CreateEnvironmentFileData (ITaskItem [] environments, out DateTime newes

using (var stream = new MemoryStream ())
using (var binaryWriter = new BinaryWriter (stream, Encoding.ASCII)) {
binaryWriter.Write (Encoding.ASCII.GetBytes ("0x" + maxKeyLength.ToString ("X8") + '\0'));
binaryWriter.Write (Encoding.ASCII.GetBytes ("0x" + maxValueLength.ToString ("X8") + '\0'));
binaryWriter.Write (Encoding.ASCII.GetBytes ("0x" + maxKeyLength.ToString ("X8", System.Globalization.CultureInfo.CurrentCulture) + '\0'));
binaryWriter.Write (Encoding.ASCII.GetBytes ("0x" + maxValueLength.ToString ("X8", System.Globalization.CultureInfo.CurrentCulture) + '\0'));
foreach (var kvp in data) {
binaryWriter.Write (Encoding.ASCII.GetBytes (kvp.Key.PadRight (maxKeyLength, '\0')));
binaryWriter.Write (Encoding.ASCII.GetBytes (kvp.Value.PadRight (maxValueLength, '\0')));
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
#nullable disable
using System.Collections.Generic;
using System.Text.Json.Serialization;

namespace Xamarin.Android.Tasks
namespace Microsoft.Android.Tasks
{
[JsonSourceGenerationOptions (WriteIndented = true)]
[JsonSerializable (typeof (FastDeploy.ManifestData))]
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
using System;
using System.Collections.Generic;
using System.IO;
using Microsoft.Build.Framework;
using NUnit.Framework;
using Microsoft.Android.Tasks;
using Xamarin.Android.Tasks;
using Xamarin.Android.Tools;

namespace Xamarin.Android.Build.Tests
{
public partial class FastDeployTests
{
// Xamarin.Android.Build.Debugging.Tasks.dll (GetPrimaryCpuAbi) caches the selected device under this key.
static object DeviceCacheKey (string target, string adbPath) =>
Tuple.Create ("AndroidHelper_AndroidDevice", target, adbPath);

[Test]
public void FastDeployReusesDeviceSelectedByDebuggingTasks ()
{
string adbToolPath = Path.Combine (Path.GetTempPath (), "missing-" + Guid.NewGuid ().ToString ("N"));
IBuildEngine4 engine = new MockBuildEngine (TestContext.Out);
engine.RegisterTaskObject (DeviceCacheKey ("-s emulator-5554", Path.Combine (adbToolPath, "adb")), new object [] {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤖 💡 Testing — Consider checking in the cross-task counting-fake-adb fixture described in the PR: let the actual GetPrimaryCpuAbi task populate the cache, then run FastDeploy through the shipped targets and assert that only one adb devices -l invocation occurred. This test hand-registers the expected payload and calls only the modern assembly's AndroidHelper, so it verifies cache consumption but cannot catch producer-side key/payload drift or assembly-loading differences between the two task assemblies. The manual smoke test is good evidence for this revision; preserving it as a regression test would protect the main reason for the shared-cache change.

{Rule: Test cross-assembly behavior at the consuming boundary}

"emulator-5554", "sdk_gphone64_arm64", (int) AdbDeviceType.Emulator, (int) AdbDeviceStatus.Online, null,
"sdk_gphone64_arm64", "sdk_gphone64_arm64", "emu64a", "1", "emulator-5554 device transport_id:1",
}, RegisteredTaskObjectLifetime.Build, false);
var messages = new List<string> ();
var errors = new List<string> ();

var device = AndroidHelper.ParseTarget ("-s emulator-5554", messages.Add, (code, message) => errors.Add (message),
logErrors: true, engine4: engine, adbToolPath: adbToolPath, adbToolExe: "adb");

Assert.IsEmpty (errors, "adb must not run when another task assembly already selected the device.");
CollectionAssert.Contains (messages, "Using cached value from RegisterTaskObject");
Assert.IsNotNull (device);
Assert.AreEqual ("emulator-5554", device.Serial);
Assert.AreEqual ("sdk_gphone64_arm64", device.Description);
Assert.IsTrue (device.IsEmulator);
Assert.AreEqual (AdbDeviceStatus.Online, device.Status);
Assert.IsNull (device.AvdName);
Assert.AreEqual ("sdk_gphone64_arm64", device.Model);
Assert.AreEqual ("sdk_gphone64_arm64", device.Product);
Assert.AreEqual ("emu64a", device.Device);
Assert.AreEqual ("1", device.TransportId);
Assert.AreEqual ("emulator-5554 device transport_id:1", device.LongOutput);
}

[Test]
public void FastDeployReusesMissingDeviceSelectedByDebuggingTasks ()
{
string adbToolPath = Path.Combine (Path.GetTempPath (), "missing-" + Guid.NewGuid ().ToString ("N"));
IBuildEngine4 engine = new MockBuildEngine (TestContext.Out);
engine.RegisterTaskObject (DeviceCacheKey ("", Path.Combine (adbToolPath, "adb")), new object [0], RegisteredTaskObjectLifetime.Build, false);
var errors = new List<string> ();

var device = AndroidHelper.ParseTarget ("", _ => { }, (code, message) => errors.Add ($"{code}: {message}"),
logErrors: true, engine4: engine, adbToolPath: adbToolPath, adbToolExe: "adb");

Assert.IsNull (device);
CollectionAssert.AreEqual (new [] { $"XA0010: {Xamarin.Android.Build.Debugging.Tasks.Properties.Resources.XA0010_NoDevice}" }, errors);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

namespace Xamarin.Android.Build.Tests
{
public partial class DebuggingTasksTests
public partial class FastDeployTests
{
[Test]
public void FastDeployRejectsFailedOverrideCommand (
Expand Down
Loading