From a595dcbac78cd35bfdb441a3a1fd4e625bf538bb Mon Sep 17 00:00:00 2001 From: Milos Kotlar Date: Wed, 22 Jul 2026 09:10:49 +0200 Subject: [PATCH 1/7] [XABT] Track libxamarin-app.so as a _BuildApkFastDev input The `_BuildApkFastDev` target packages the generated typemap library `@(_ApplicationSharedLibrary)` into the APK but does not list that item in `_BuildApkFastDevStaticInputs`, so when a source edit changes the app assembly MVID and `_CreateApplicationSharedLibraries` relinks `libxamarin-app.so` with a new CoreCLR Debug typemap, MSBuild treats the target as up to date and skips repackaging, after which Fast Deploy pushes the new assembly to `.__override__` while the installed APK keeps the stale typemap and the managed to Java lookup resolves an application `Activity` to `java.lang.Object` and raises `ActivityNotFoundException` on the next launch. The mismatch surfaces on CoreCLR because its Debug typemap is MVID keyed by #10065 whereas the Mono typemap is independent of the MVID, and the missing input has existed since `_BuildApkFastDev` moved into this repository in #9364, so adding `@(_ApplicationSharedLibrary)` to `_BuildApkFastDevStaticInputs` to match the sibling `_BuildApkEmbedInputs` rebuilds and reinstalls the APK whenever the typemap library changes and fixes #12201. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: fd64bd8f-1056-4745-8aad-7e13d81dfad7 --- src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets b/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets index ea3cf49c141..b8e9f47f91c 100644 --- a/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets +++ b/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets @@ -2324,6 +2324,7 @@ because xbuild doesn't support framework reference assemblies. ;@(_ShrunkFrameworkAssemblies) ;@(_AndroidNativeLibraryForFastDev) ;@(_DexFileForFastDevInput) + ;@(_ApplicationSharedLibrary) ;$(_AndroidBuildPropertiesCache) ;$(_AdbPropertiesCache) ;$(_PackagedResources) From f38aa8a8de92648fe006dedc483becd4ab5f7a48 Mon Sep 17 00:00:00 2001 From: David Nguyen <87228593+davidnguyen-tech@users.noreply.github.com> Date: Wed, 22 Jul 2026 12:38:27 +0200 Subject: [PATCH 2/7] [Tests] Add CoreCLR Fast Deploy incremental coverage Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 84bdb893-d6de-4a7c-a405-55f811a0bd28 --- .../IncrementalBuildTest.cs | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/IncrementalBuildTest.cs b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/IncrementalBuildTest.cs index 0c17988fe71..ea0a0c7eb04 100644 --- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/IncrementalBuildTest.cs +++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/IncrementalBuildTest.cs @@ -1323,6 +1323,29 @@ public void CasingOnJavaLangObject ([Values (AndroidRuntime.CoreCLR, AndroidRunt } } + [Test] + public void CoreClrFastDeploymentRebuildsApkAfterAssemblyChange () + { + if (IgnoreUnsupportedConfiguration (AndroidRuntime.CoreCLR)) { + return; + } + + var proj = new XamarinAndroidApplicationProject { + EmbedAssembliesIntoApk = false, + }; + proj.SetRuntime (AndroidRuntime.CoreCLR); + proj.MainActivity = proj.DefaultMainActivity; + using (var b = CreateApkBuilder ()) { + Assert.IsTrue (b.Build (proj), "first build should have succeeded."); + + proj.MainActivity += Environment.NewLine + "// comment"; + proj.Touch ("MainActivity.cs"); + Assert.IsTrue (b.Build (proj), "second build should have succeeded."); + Assert.IsTrue (b.Output.IsTargetSkipped ("_CompileToDalvik"), "`_CompileToDalvik` should be skipped!"); + Assert.IsFalse (b.Output.IsTargetSkipped ("_BuildApkFastDev"), "`_BuildApkFastDev` should *not* be skipped!"); + } + } + [Test] public void GenerateJavaStubsAndAssembly ([Values] bool isRelease, [Values (AndroidRuntime.CoreCLR, AndroidRuntime.NativeAOT)] AndroidRuntime runtime) { From 9ea04c01abfa4313768bd5392c52c1b435e11849 Mon Sep 17 00:00:00 2001 From: Jonathan Peppers Date: Wed, 22 Jul 2026 08:26:11 -0500 Subject: [PATCH 3/7] [Tests] Exercise Fast Deploy typemap updates on device Replace the target-scheduling test with an MSBuildDeviceIntegration test that verifies an app-defined activity still resolves after an incremental assembly update. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: c74c08f8-5d07-4567-ac35-9de7021e5a4a --- .../IncrementalBuildTest.cs | 23 ---------- .../Tests/FastDevTest.cs | 43 +++++++++++++++++++ 2 files changed, 43 insertions(+), 23 deletions(-) diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/IncrementalBuildTest.cs b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/IncrementalBuildTest.cs index ea0a0c7eb04..0c17988fe71 100644 --- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/IncrementalBuildTest.cs +++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/IncrementalBuildTest.cs @@ -1323,29 +1323,6 @@ public void CasingOnJavaLangObject ([Values (AndroidRuntime.CoreCLR, AndroidRunt } } - [Test] - public void CoreClrFastDeploymentRebuildsApkAfterAssemblyChange () - { - if (IgnoreUnsupportedConfiguration (AndroidRuntime.CoreCLR)) { - return; - } - - var proj = new XamarinAndroidApplicationProject { - EmbedAssembliesIntoApk = false, - }; - proj.SetRuntime (AndroidRuntime.CoreCLR); - proj.MainActivity = proj.DefaultMainActivity; - using (var b = CreateApkBuilder ()) { - Assert.IsTrue (b.Build (proj), "first build should have succeeded."); - - proj.MainActivity += Environment.NewLine + "// comment"; - proj.Touch ("MainActivity.cs"); - Assert.IsTrue (b.Build (proj), "second build should have succeeded."); - Assert.IsTrue (b.Output.IsTargetSkipped ("_CompileToDalvik"), "`_CompileToDalvik` should be skipped!"); - Assert.IsFalse (b.Output.IsTargetSkipped ("_BuildApkFastDev"), "`_BuildApkFastDev` should *not* be skipped!"); - } - } - [Test] public void GenerateJavaStubsAndAssembly ([Values] bool isRelease, [Values (AndroidRuntime.CoreCLR, AndroidRuntime.NativeAOT)] AndroidRuntime runtime) { diff --git a/tests/MSBuildDeviceIntegration/Tests/FastDevTest.cs b/tests/MSBuildDeviceIntegration/Tests/FastDevTest.cs index 697274e0cb6..c5ad02be56b 100644 --- a/tests/MSBuildDeviceIntegration/Tests/FastDevTest.cs +++ b/tests/MSBuildDeviceIntegration/Tests/FastDevTest.cs @@ -157,6 +157,49 @@ public void SkipFastDevAlreadyInstalledFile () b.Dispose (); } + [Test] + public void FastDeployUpdatesTypeMapAfterAssemblyEdit () + { + var proj = new XamarinAndroidApplicationProject { + PackageName = "com.xamarin.fastdeploy_typemap", + }; + proj.SetDefaultTargetDevice (); + proj.SetProperty ("_AndroidFastDevStrategy", "FastDeploy"); + proj.MainActivity = proj.DefaultMainActivity + .Replace ("//${AFTER_ONCREATE}", "StartActivity (new Android.Content.Intent (this, typeof (SecondActivity)));") + .Replace ("//${AFTER_MAINACTIVITY}", """ + [Activity (Label = "Fast Deploy Result")] + public sealed class SecondActivity : Activity + { + } + """); + + using var builder = CreateApkBuilder (); + Assert.IsTrue (builder.Install (proj), "Initial install should have succeeded."); + AssertSecondActivityStarts ("initial-launch.log"); + + proj.MainActivity += "// Incremental C# edit."; + proj.Touch ("MainActivity.cs"); + Assert.IsTrue (builder.Install (proj, doNotCleanupOnUpdate: true, saveProject: false), "Incremental install should have succeeded."); + AssertSecondActivityStarts ("incremental-launch.log"); + Assert.IsTrue (builder.Uninstall (proj), "Uninstall should have succeeded."); + + void AssertSecondActivityStarts (string logFileName) + { + ClearAdbLogcat (); + AdbStartActivity ($"{proj.PackageName}/{proj.JavaPackageName}.MainActivity"); + Assert.IsTrue ( + WaitForActivityToStart ( + proj.PackageName, + "SecondActivity", + Path.Combine (Root, builder.ProjectDirectory, logFileName), + ActivityStartTimeoutInSeconds + ), + "SecondActivity should have started." + ); + } + } + #pragma warning disable 414 static object [] SkipFastDevAlreadyInstalledResourcesSource = new object [] { new object[] { Array.Empty (), null }, From 4a6b83313366c7cabfc0f50784bf4d0bab04c118 Mon Sep 17 00:00:00 2001 From: Jonathan Peppers Date: Wed, 22 Jul 2026 09:07:34 -0500 Subject: [PATCH 4/7] [Tests] Resolve FastDev coverage with main Carry forward the FastDeploy2 tests added on main while retaining the incremental typemap device regression. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: c74c08f8-5d07-4567-ac35-9de7021e5a4a --- .../Tests/FastDevTest.cs | 67 +++++++++++++++++++ 1 file changed, 67 insertions(+) diff --git a/tests/MSBuildDeviceIntegration/Tests/FastDevTest.cs b/tests/MSBuildDeviceIntegration/Tests/FastDevTest.cs index c5ad02be56b..ce9e75b0aca 100644 --- a/tests/MSBuildDeviceIntegration/Tests/FastDevTest.cs +++ b/tests/MSBuildDeviceIntegration/Tests/FastDevTest.cs @@ -200,6 +200,73 @@ void AssertSecondActivityStarts (string logFileName) } } + [Test] + public void FastDeploymentStrategyCanBeChanged () + { + var proj = new XamarinAndroidApplicationProject { + PackageName = "com.xamarin.fastdeployment_strategy_change", + }; + proj.MainActivity = proj.DefaultMainActivity; + proj.SetDefaultTargetDevice (); + proj.SetProperty ("_AndroidFastDevStrategy", "FastDeploy2"); + using (var builder = CreateApkBuilder ()) { + builder.Verbosity = LoggerVerbosity.Detailed; + Assert.IsTrue (builder.Install (proj), "FastDeploy2 install should have succeeded."); + + string assemblyPath = $"files/.__override__/{DeviceAbi}/UnnamedProject.dll"; + Assert.AreEqual ("symlink", GetOverrideFileKind (proj.PackageName, assemblyPath)); + RunAdbCommand ($"shell run-as {proj.PackageName} sh -c 'echo preserved > files/fastdeploy-strategy-marker'"); + Assert.IsTrue (builder.Clean (proj), "clean should have succeeded."); + + proj.MainActivity = proj.MainActivity.Replace ("clicks", "CLICKS"); + proj.Touch ("MainActivity.cs"); + proj.SetProperty ("_AndroidFastDevStrategy", "FastDeploy"); + Assert.IsTrue (builder.Install (proj, doNotCleanupOnUpdate: true), "FastDeploy install should have succeeded after FastDeploy2."); + Assert.AreEqual ("regular", GetOverrideFileKind (proj.PackageName, assemblyPath)); + Assert.AreEqual ("preserved", RunAdbCommand ($"shell run-as {proj.PackageName} cat files/fastdeploy-strategy-marker").Trim ()); + + proj.MainActivity = proj.MainActivity.Replace ("CLICKS", "Clicks"); + proj.Touch ("MainActivity.cs"); + proj.SetProperty ("_AndroidFastDevStrategy", "FastDeploy2"); + Assert.IsTrue (builder.Install (proj, doNotCleanupOnUpdate: true), "FastDeploy2 install should have succeeded after FastDeploy."); + Assert.AreEqual ("symlink", GetOverrideFileKind (proj.PackageName, assemblyPath)); + Assert.AreEqual ("preserved", RunAdbCommand ($"shell run-as {proj.PackageName} cat files/fastdeploy-strategy-marker").Trim ()); + + Assert.IsTrue (builder.Uninstall (proj), "uninstall should have succeeded."); + } + } + + [Test] + public void FastDeploy2RestoresMissingRemoteDirectory () + { + var proj = new XamarinAndroidApplicationProject { + PackageName = "com.xamarin.fastdeploy2_restore_remote", + }; + proj.MainActivity = proj.DefaultMainActivity; + proj.SetDefaultTargetDevice (); + using (var builder = CreateApkBuilder ()) { + builder.Verbosity = LoggerVerbosity.Detailed; + Assert.IsTrue (builder.Install (proj), "initial install should have succeeded."); + + string remoteDirectory = $"/data/local/tmp/fastdeploy2/{proj.PackageName}/0/{DeviceAbi}"; + RunAdbCommand ($"shell rm -rf {remoteDirectory}"); + + proj.MainActivity = proj.MainActivity.Replace ("clicks", "CLICKS"); + proj.Touch ("MainActivity.cs"); + Assert.IsTrue (builder.Install (proj, doNotCleanupOnUpdate: true), "fresh deployment fallback should have succeeded."); + + string assemblyPath = $"files/.__override__/{DeviceAbi}/UnnamedProject.dll"; + Assert.AreEqual ("symlink", GetOverrideFileKind (proj.PackageName, assemblyPath)); + Assert.AreEqual ("exists", RunAdbCommand ($"shell if test -f {remoteDirectory}/UnnamedProject.dll; then echo exists; else echo missing; fi").Trim ()); + Assert.IsTrue (builder.Uninstall (proj), "uninstall should have succeeded."); + } + } + + string GetOverrideFileKind (string packageName, string path) + { + return RunAdbCommand ($"shell run-as {packageName} sh -c 'if test -L {path}; then echo symlink; elif test -f {path}; then echo regular; else echo missing; fi'").Trim (); + } + #pragma warning disable 414 static object [] SkipFastDevAlreadyInstalledResourcesSource = new object [] { new object[] { Array.Empty (), null }, From 820b2c418de952357fadaa299211da1fdc4328e7 Mon Sep 17 00:00:00 2001 From: Jonathan Peppers Date: Wed, 22 Jul 2026 09:08:41 -0500 Subject: [PATCH 5/7] [Tests] Avoid FastDev merge overlap Place the typemap regression beside the stable Fast Deploy tests so current main can merge without overlapping the FastDeploy2 additions. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: c74c08f8-5d07-4567-ac35-9de7021e5a4a --- .../Tests/FastDevTest.cs | 86 +++++++++---------- 1 file changed, 43 insertions(+), 43 deletions(-) diff --git a/tests/MSBuildDeviceIntegration/Tests/FastDevTest.cs b/tests/MSBuildDeviceIntegration/Tests/FastDevTest.cs index ce9e75b0aca..93db824e499 100644 --- a/tests/MSBuildDeviceIntegration/Tests/FastDevTest.cs +++ b/tests/MSBuildDeviceIntegration/Tests/FastDevTest.cs @@ -38,6 +38,49 @@ public void FastDevSimpleBuild () b.Dispose (); } + [Test] + public void FastDeployUpdatesTypeMapAfterAssemblyEdit () + { + var proj = new XamarinAndroidApplicationProject { + PackageName = "com.xamarin.fastdeploy_typemap", + }; + proj.SetDefaultTargetDevice (); + proj.SetProperty ("_AndroidFastDevStrategy", "FastDeploy"); + proj.MainActivity = proj.DefaultMainActivity + .Replace ("//${AFTER_ONCREATE}", "StartActivity (new Android.Content.Intent (this, typeof (SecondActivity)));") + .Replace ("//${AFTER_MAINACTIVITY}", """ + [Activity (Label = "Fast Deploy Result")] + public sealed class SecondActivity : Activity + { + } + """); + + using var builder = CreateApkBuilder (); + Assert.IsTrue (builder.Install (proj), "Initial install should have succeeded."); + AssertSecondActivityStarts ("initial-launch.log"); + + proj.MainActivity += "// Incremental C# edit."; + proj.Touch ("MainActivity.cs"); + Assert.IsTrue (builder.Install (proj, doNotCleanupOnUpdate: true, saveProject: false), "Incremental install should have succeeded."); + AssertSecondActivityStarts ("incremental-launch.log"); + Assert.IsTrue (builder.Uninstall (proj), "Uninstall should have succeeded."); + + void AssertSecondActivityStarts (string logFileName) + { + ClearAdbLogcat (); + AdbStartActivity ($"{proj.PackageName}/{proj.JavaPackageName}.MainActivity"); + Assert.IsTrue ( + WaitForActivityToStart ( + proj.PackageName, + "SecondActivity", + Path.Combine (Root, builder.ProjectDirectory, logFileName), + ActivityStartTimeoutInSeconds + ), + "SecondActivity should have started." + ); + } + } + [Test] public void TargetsSkipped ([Values(false, true)] bool useManagedResourceGenerator) { @@ -157,49 +200,6 @@ public void SkipFastDevAlreadyInstalledFile () b.Dispose (); } - [Test] - public void FastDeployUpdatesTypeMapAfterAssemblyEdit () - { - var proj = new XamarinAndroidApplicationProject { - PackageName = "com.xamarin.fastdeploy_typemap", - }; - proj.SetDefaultTargetDevice (); - proj.SetProperty ("_AndroidFastDevStrategy", "FastDeploy"); - proj.MainActivity = proj.DefaultMainActivity - .Replace ("//${AFTER_ONCREATE}", "StartActivity (new Android.Content.Intent (this, typeof (SecondActivity)));") - .Replace ("//${AFTER_MAINACTIVITY}", """ - [Activity (Label = "Fast Deploy Result")] - public sealed class SecondActivity : Activity - { - } - """); - - using var builder = CreateApkBuilder (); - Assert.IsTrue (builder.Install (proj), "Initial install should have succeeded."); - AssertSecondActivityStarts ("initial-launch.log"); - - proj.MainActivity += "// Incremental C# edit."; - proj.Touch ("MainActivity.cs"); - Assert.IsTrue (builder.Install (proj, doNotCleanupOnUpdate: true, saveProject: false), "Incremental install should have succeeded."); - AssertSecondActivityStarts ("incremental-launch.log"); - Assert.IsTrue (builder.Uninstall (proj), "Uninstall should have succeeded."); - - void AssertSecondActivityStarts (string logFileName) - { - ClearAdbLogcat (); - AdbStartActivity ($"{proj.PackageName}/{proj.JavaPackageName}.MainActivity"); - Assert.IsTrue ( - WaitForActivityToStart ( - proj.PackageName, - "SecondActivity", - Path.Combine (Root, builder.ProjectDirectory, logFileName), - ActivityStartTimeoutInSeconds - ), - "SecondActivity should have started." - ); - } - } - [Test] public void FastDeploymentStrategyCanBeChanged () { From ec2e2386cfdd20b813643cfaaf621c324869a610 Mon Sep 17 00:00:00 2001 From: Jonathan Peppers Date: Wed, 22 Jul 2026 09:10:55 -0500 Subject: [PATCH 6/7] [Tests] Keep FastDev PR diff focused Leave the FastDeploy2 coverage to main and retain only the typemap regression at a non-overlapping insertion point. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: c74c08f8-5d07-4567-ac35-9de7021e5a4a --- .../Tests/FastDevTest.cs | 67 ------------------- 1 file changed, 67 deletions(-) diff --git a/tests/MSBuildDeviceIntegration/Tests/FastDevTest.cs b/tests/MSBuildDeviceIntegration/Tests/FastDevTest.cs index 93db824e499..0c6a2ff5b06 100644 --- a/tests/MSBuildDeviceIntegration/Tests/FastDevTest.cs +++ b/tests/MSBuildDeviceIntegration/Tests/FastDevTest.cs @@ -200,73 +200,6 @@ public void SkipFastDevAlreadyInstalledFile () b.Dispose (); } - [Test] - public void FastDeploymentStrategyCanBeChanged () - { - var proj = new XamarinAndroidApplicationProject { - PackageName = "com.xamarin.fastdeployment_strategy_change", - }; - proj.MainActivity = proj.DefaultMainActivity; - proj.SetDefaultTargetDevice (); - proj.SetProperty ("_AndroidFastDevStrategy", "FastDeploy2"); - using (var builder = CreateApkBuilder ()) { - builder.Verbosity = LoggerVerbosity.Detailed; - Assert.IsTrue (builder.Install (proj), "FastDeploy2 install should have succeeded."); - - string assemblyPath = $"files/.__override__/{DeviceAbi}/UnnamedProject.dll"; - Assert.AreEqual ("symlink", GetOverrideFileKind (proj.PackageName, assemblyPath)); - RunAdbCommand ($"shell run-as {proj.PackageName} sh -c 'echo preserved > files/fastdeploy-strategy-marker'"); - Assert.IsTrue (builder.Clean (proj), "clean should have succeeded."); - - proj.MainActivity = proj.MainActivity.Replace ("clicks", "CLICKS"); - proj.Touch ("MainActivity.cs"); - proj.SetProperty ("_AndroidFastDevStrategy", "FastDeploy"); - Assert.IsTrue (builder.Install (proj, doNotCleanupOnUpdate: true), "FastDeploy install should have succeeded after FastDeploy2."); - Assert.AreEqual ("regular", GetOverrideFileKind (proj.PackageName, assemblyPath)); - Assert.AreEqual ("preserved", RunAdbCommand ($"shell run-as {proj.PackageName} cat files/fastdeploy-strategy-marker").Trim ()); - - proj.MainActivity = proj.MainActivity.Replace ("CLICKS", "Clicks"); - proj.Touch ("MainActivity.cs"); - proj.SetProperty ("_AndroidFastDevStrategy", "FastDeploy2"); - Assert.IsTrue (builder.Install (proj, doNotCleanupOnUpdate: true), "FastDeploy2 install should have succeeded after FastDeploy."); - Assert.AreEqual ("symlink", GetOverrideFileKind (proj.PackageName, assemblyPath)); - Assert.AreEqual ("preserved", RunAdbCommand ($"shell run-as {proj.PackageName} cat files/fastdeploy-strategy-marker").Trim ()); - - Assert.IsTrue (builder.Uninstall (proj), "uninstall should have succeeded."); - } - } - - [Test] - public void FastDeploy2RestoresMissingRemoteDirectory () - { - var proj = new XamarinAndroidApplicationProject { - PackageName = "com.xamarin.fastdeploy2_restore_remote", - }; - proj.MainActivity = proj.DefaultMainActivity; - proj.SetDefaultTargetDevice (); - using (var builder = CreateApkBuilder ()) { - builder.Verbosity = LoggerVerbosity.Detailed; - Assert.IsTrue (builder.Install (proj), "initial install should have succeeded."); - - string remoteDirectory = $"/data/local/tmp/fastdeploy2/{proj.PackageName}/0/{DeviceAbi}"; - RunAdbCommand ($"shell rm -rf {remoteDirectory}"); - - proj.MainActivity = proj.MainActivity.Replace ("clicks", "CLICKS"); - proj.Touch ("MainActivity.cs"); - Assert.IsTrue (builder.Install (proj, doNotCleanupOnUpdate: true), "fresh deployment fallback should have succeeded."); - - string assemblyPath = $"files/.__override__/{DeviceAbi}/UnnamedProject.dll"; - Assert.AreEqual ("symlink", GetOverrideFileKind (proj.PackageName, assemblyPath)); - Assert.AreEqual ("exists", RunAdbCommand ($"shell if test -f {remoteDirectory}/UnnamedProject.dll; then echo exists; else echo missing; fi").Trim ()); - Assert.IsTrue (builder.Uninstall (proj), "uninstall should have succeeded."); - } - } - - string GetOverrideFileKind (string packageName, string path) - { - return RunAdbCommand ($"shell run-as {packageName} sh -c 'if test -L {path}; then echo symlink; elif test -f {path}; then echo regular; else echo missing; fi'").Trim (); - } - #pragma warning disable 414 static object [] SkipFastDevAlreadyInstalledResourcesSource = new object [] { new object[] { Array.Empty (), null }, From 744199accff78cdb795d0057b57f3f65da8995b3 Mon Sep 17 00:00:00 2001 From: Jonathan Peppers Date: Wed, 22 Jul 2026 16:11:22 -0500 Subject: [PATCH 7/7] [Tests] Expect APK reinstall after CoreCLR source edit Updating the app assembly regenerates libxamarin-app.so, so the incremental install correctly reinstalls the APK while still Fast Deploying only changed managed assemblies. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 5178fba3-c160-4fb4-90bc-9b581b36408f --- tests/MSBuildDeviceIntegration/Tests/FastDevTest.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/MSBuildDeviceIntegration/Tests/FastDevTest.cs b/tests/MSBuildDeviceIntegration/Tests/FastDevTest.cs index 0c6a2ff5b06..3f0e140b3ed 100644 --- a/tests/MSBuildDeviceIntegration/Tests/FastDevTest.cs +++ b/tests/MSBuildDeviceIntegration/Tests/FastDevTest.cs @@ -183,7 +183,7 @@ public void SkipFastDevAlreadyInstalledFile () proj.Touch ("MainActivity.cs"); // make sure that the fastdev log tells that the relevant dll is updated but NOT for others. Assert.IsTrue (b.Install (proj, doNotCleanupOnUpdate: true, saveProject: false), "install should have succeeded."); - Assert.IsFalse (b.Output.IsApkInstalled, "app apk was installed"); + Assert.IsTrue (b.Output.IsApkInstalled, "app apk was not installed"); Assert.IsTrue (b.LastBuildOutput.Any (l => l.Contains ("UnnamedProject.dll") && l.Contains ("NotifySync CopyFile")), "app dll not uploaded"); var assemblies = new[] {