From a444e8aa5343f9635a03320e68b4b80c2717066c Mon Sep 17 00:00:00 2001 From: Marek Habersack Date: Mon, 8 Dec 2025 13:37:56 +0100 Subject: [PATCH 01/25] Introduce a package naming helper On-device tests which run the same project but with different runtimes must use different package names or we might find ourselves in a situation when an application built for a different runtime and installed over a previous version which uses another runtime, won't even start. This happened with NativeAOT in the InstallAndRunTests.DotNetRun test. --- .../Utilities/PackageUtils.cs | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/Utilities/PackageUtils.cs diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/Utilities/PackageUtils.cs b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/Utilities/PackageUtils.cs new file mode 100644 index 00000000000..c9e3e85bb29 --- /dev/null +++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/Utilities/PackageUtils.cs @@ -0,0 +1,28 @@ +using System; +using System.Runtime.CompilerServices; +using System.Text; +using Xamarin.Android.Tasks; +using Xamarin.ProjectTools; + +namespace Xamarin.Android.Build.Tests; + +class PackageUtils +{ + /// + /// Constructs Android package name parameter for the which includes + /// the runtime used to build and run the application. A unique per-runtime package name is necessary so that elements + /// of different runtimes don't mix when running the same test for several of them. + /// + public static string MakePackageName (AndroidRuntime runtime, [CallerMemberName] string packageName = "") + { + if (String.IsNullOrEmpty (packageName)) { + throw new ArgumentException ("Must not be null or empty", nameof (packageName)); + } + + var sb = new StringBuilder (packageName); + sb.Append ('_'); + sb.Append (runtime.ToString ().ToLowerInvariant ()); + + return sb.ToString (); + } +} From 55bb8b9261e17888054b2fef7ed054c554b92a9b Mon Sep 17 00:00:00 2001 From: Marek Habersack Date: Mon, 8 Dec 2025 13:39:26 +0100 Subject: [PATCH 02/25] InstallAndRunTests.DotNetRun works --- .../Tests/InstallAndRunTests.cs | 43 ++++++++++++++++--- 1 file changed, 36 insertions(+), 7 deletions(-) diff --git a/tests/MSBuildDeviceIntegration/Tests/InstallAndRunTests.cs b/tests/MSBuildDeviceIntegration/Tests/InstallAndRunTests.cs index b0a1594b404..0a16a7df66a 100644 --- a/tests/MSBuildDeviceIntegration/Tests/InstallAndRunTests.cs +++ b/tests/MSBuildDeviceIntegration/Tests/InstallAndRunTests.cs @@ -29,17 +29,46 @@ public void Teardown () proj = null; } + static IEnumerable Get_DotNetRun_Data () + { + var ret = new List (); + + foreach (AndroidRuntime runtime in Enum.GetValues (typeof (AndroidRuntime))) { + AddTestData (true, "llvm-ir", runtime); + AddTestData (false, "llvm-ir", runtime); + AddTestData (true, "managed", runtime); + // NOTE: TypeMappingStep is not yet setup for Debug mode + //AddTestData (false, "managed", runtime); + } + + return ret; + + void AddTestData (bool isRelease, string typemapImplementation, AndroidRuntime runtime) + { + ret.Add (new object[] { + isRelease, + typemapImplementation, + runtime, + }); + } + } + [Test] - [TestCase (true, "llvm-ir")] - [TestCase (false, "llvm-ir")] - [TestCase (true, "managed")] - // NOTE: TypeMappingStep is not yet setup for Debug mode - //[TestCase (false, "managed")] - public void DotNetRun (bool isRelease, string typemapImplementation) + [TestCaseSource (nameof (Get_DotNetRun_Data))] + public void DotNetRun (bool isRelease, string typemapImplementation, AndroidRuntime runtime) { - var proj = new XamarinAndroidApplicationProject { + if (IgnoreUnsupportedConfiguration (runtime, release: isRelease)) { + return; + } + + if (runtime == AndroidRuntime.NativeAOT && typemapImplementation == "llvm-ir") { + Assert.Ignore ("NativeAOT doesn't work with LLVM-IR typemaps"); + } + + var proj = new XamarinAndroidApplicationProject (packageName: PackageUtils.MakePackageName (runtime)) { IsRelease = isRelease }; + proj.SetRuntime (runtime); proj.SetProperty ("_AndroidTypeMapImplementation", typemapImplementation); using var builder = CreateApkBuilder (); builder.Save (proj); From aecb0e4149bed3b50115fd3d102bd3feeb1f62cb Mon Sep 17 00:00:00 2001 From: Marek Habersack Date: Mon, 8 Dec 2025 13:46:29 +0100 Subject: [PATCH 03/25] InstallAndRunTests.ActivityAliasRuns works --- .../MSBuildDeviceIntegration/Tests/InstallAndRunTests.cs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/tests/MSBuildDeviceIntegration/Tests/InstallAndRunTests.cs b/tests/MSBuildDeviceIntegration/Tests/InstallAndRunTests.cs index 0a16a7df66a..e64bb41b166 100644 --- a/tests/MSBuildDeviceIntegration/Tests/InstallAndRunTests.cs +++ b/tests/MSBuildDeviceIntegration/Tests/InstallAndRunTests.cs @@ -119,11 +119,16 @@ public void DeployToDevice (bool isRelease) } [Test] - public void ActivityAliasRuns ([Values (true, false)] bool isRelease) + public void ActivityAliasRuns ([Values] bool isRelease, [Values] AndroidRuntime runtime) { - var proj = new XamarinAndroidApplicationProject { + if (IgnoreUnsupportedConfiguration (runtime, release: isRelease)) { + return; + } + + var proj = new XamarinAndroidApplicationProject (packageName: PackageUtils.MakePackageName (runtime)) { IsRelease = isRelease }; + proj.SetRuntime (runtime); proj.AndroidManifest = proj.AndroidManifest.Replace ("", @" Date: Mon, 8 Dec 2025 14:01:09 +0100 Subject: [PATCH 04/25] InstallAndRunTests.NativeAssemblyCacheWithSatelliteAssemblies updated --- .../Tests/InstallAndRunTests.cs | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/tests/MSBuildDeviceIntegration/Tests/InstallAndRunTests.cs b/tests/MSBuildDeviceIntegration/Tests/InstallAndRunTests.cs index e64bb41b166..11646f28df9 100644 --- a/tests/MSBuildDeviceIntegration/Tests/InstallAndRunTests.cs +++ b/tests/MSBuildDeviceIntegration/Tests/InstallAndRunTests.cs @@ -151,8 +151,17 @@ public void ActivityAliasRuns ([Values] bool isRelease, [Values] AndroidRuntime } [Test] - public void NativeAssemblyCacheWithSatelliteAssemblies ([Values (true, false)] bool enableMarshalMethods, [Values (AndroidRuntime.MonoVM, AndroidRuntime.CoreCLR)] AndroidRuntime runtime) + public void NativeAssemblyCacheWithSatelliteAssemblies ([Values] bool enableMarshalMethods, [Values] AndroidRuntime runtime) { + const bool isRelease = true; + if (IgnoreUnsupportedConfiguration (runtime, release: isRelease)) { + return; + } + + if (runtime == AndroidRuntime.NativeAOT) { + Assert.Ignore ("NativeAOT doesn't support individual assemblies"); + } + if (enableMarshalMethods && runtime == AndroidRuntime.CoreCLR) { // This currently fails with the following exception: // @@ -169,6 +178,7 @@ public void NativeAssemblyCacheWithSatelliteAssemblies ([Values (true, false)] b var path = Path.Combine ("temp", TestName); var lib = new XamarinAndroidLibraryProject { + IsRelease = isRelease, ProjectName = "Localization", OtherBuildItems = { new BuildItem ("EmbeddedResource", "Foo.resx") { @@ -187,8 +197,8 @@ public void NativeAssemblyCacheWithSatelliteAssemblies ([Values (true, false)] b ); } - proj = new XamarinAndroidApplicationProject { - IsRelease = true, + proj = new XamarinAndroidApplicationProject (packageName: PackageUtils.MakePackageName (runtime)) { + IsRelease = isRelease, EnableMarshalMethods = enableMarshalMethods, }; proj.SetRuntime (runtime); From 521bf0ded51b3571cd36583e0b285b686e9e90c5 Mon Sep 17 00:00:00 2001 From: Marek Habersack Date: Mon, 8 Dec 2025 14:10:22 +0100 Subject: [PATCH 05/25] InstallAndRunTests.GlobalLayoutEvent_ShouldRegisterAndFire_OnActivityLaunch works --- .../Tests/InstallAndRunTests.cs | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/tests/MSBuildDeviceIntegration/Tests/InstallAndRunTests.cs b/tests/MSBuildDeviceIntegration/Tests/InstallAndRunTests.cs index 11646f28df9..671acde887c 100644 --- a/tests/MSBuildDeviceIntegration/Tests/InstallAndRunTests.cs +++ b/tests/MSBuildDeviceIntegration/Tests/InstallAndRunTests.cs @@ -223,13 +223,15 @@ public void NativeAssemblyCacheWithSatelliteAssemblies ([Values] bool enableMars } [Test] - public void GlobalLayoutEvent_ShouldRegisterAndFire_OnActivityLaunch ( - [Values (false, true)] bool isRelease, - [Values (AndroidRuntime.MonoVM, AndroidRuntime.CoreCLR)] AndroidRuntime runtime) + public void GlobalLayoutEvent_ShouldRegisterAndFire_OnActivityLaunch ([Values] bool isRelease, [Values] AndroidRuntime runtime) { + if (IgnoreUnsupportedConfiguration (runtime, release: isRelease)) { + return; + } + string expectedLogcatOutput = "Bug 29730: GlobalLayout event handler called!"; - proj = new XamarinAndroidApplicationProject () { + proj = new XamarinAndroidApplicationProject (packageName: PackageUtils.MakePackageName (runtime)) { IsRelease = isRelease, SupportedOSPlatformVersion = "23", }; From 53e79faec727f95917841b3e3ca66a5123f35ecf Mon Sep 17 00:00:00 2001 From: Marek Habersack Date: Mon, 8 Dec 2025 14:21:59 +0100 Subject: [PATCH 06/25] InstallAndRunTests.SubscribeToAppDomainUnhandledException updated --- .../Tests/InstallAndRunTests.cs | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/tests/MSBuildDeviceIntegration/Tests/InstallAndRunTests.cs b/tests/MSBuildDeviceIntegration/Tests/InstallAndRunTests.cs index 671acde887c..fc9958e4f03 100644 --- a/tests/MSBuildDeviceIntegration/Tests/InstallAndRunTests.cs +++ b/tests/MSBuildDeviceIntegration/Tests/InstallAndRunTests.cs @@ -259,17 +259,22 @@ void Button_ViewTreeObserver_GlobalLayout (object sender, EventArgs e) }, Path.Combine (Root, builder.ProjectDirectory, "startup-logcat.log"), 60), $"Output did not contain {expectedLogcatOutput}!"); } - // TODO: check if AppDomain.CurrentDomain.UnhandledException even works in CoreCLR + // TODO: check if AppDomain.CurrentDomain.UnhandledException even works in CoreCLR and NativeAOT [Test] - public void SubscribeToAppDomainUnhandledException ([Values (AndroidRuntime.MonoVM, AndroidRuntime.CoreCLR)] AndroidRuntime runtime) + public void SubscribeToAppDomainUnhandledException ([Values] AndroidRuntime runtime) { - if (runtime == AndroidRuntime.CoreCLR) { - Assert.Ignore ("AppDomain.CurrentDomain.UnhandledException doesn't work in CoreCLR"); + const bool isRelease = true; + if (IgnoreUnsupportedConfiguration (runtime, release: isRelease)) { return; } - proj = new XamarinAndroidApplicationProject () { - IsRelease = true, + if (runtime == AndroidRuntime.CoreCLR || runtime == AndroidRuntime.NativeAOT) { + Assert.Ignore ("AppDomain.CurrentDomain.UnhandledException doesn't work in CoreCLR or NativeAOT"); + return; + } + + proj = new XamarinAndroidApplicationProject (packageName: PackageUtils.MakePackageName (runtime)) { + IsRelease = isRelease, }; proj.SetRuntime (runtime); if (runtime == AndroidRuntime.MonoVM) { From 62b1ddf74ed20f91fee418cfb7fee062b2faf392 Mon Sep 17 00:00:00 2001 From: Marek Habersack Date: Mon, 8 Dec 2025 14:56:37 +0100 Subject: [PATCH 07/25] InstallAndRunTests.SmokeTestBuildAndRunWithSpecialCharacters updated, broken on NativeAOT --- .../Tests/InstallAndRunTests.cs | 50 ++++++++++++++++--- 1 file changed, 44 insertions(+), 6 deletions(-) diff --git a/tests/MSBuildDeviceIntegration/Tests/InstallAndRunTests.cs b/tests/MSBuildDeviceIntegration/Tests/InstallAndRunTests.cs index fc9958e4f03..b1490328e2f 100644 --- a/tests/MSBuildDeviceIntegration/Tests/InstallAndRunTests.cs +++ b/tests/MSBuildDeviceIntegration/Tests/InstallAndRunTests.cs @@ -331,18 +331,56 @@ void Reset () } } + static IEnumerable Get_SmokeTestBuildAndRunWithSpecialCharacters_Data () + { + var ret = new List (); + + foreach (AndroidRuntime runtime in Enum.GetValues (typeof (AndroidRuntime))) { + AddTestData ("テスト", runtime); + AddTestData ("随机生成器", runtime); + AddTestData ("中国", runtime); + } + + return ret; + + void AddTestData (string testName, AndroidRuntime runtime) + { + ret.Add (new object[] { + testName, + runtime, + }); + } + } + [Test] [Category ("UsesDevice")] - [TestCase ("テスト")] - [TestCase ("随机生成器")] - [TestCase ("中国")] - public void SmokeTestBuildAndRunWithSpecialCharacters (string testName) + [TestCaseSource (nameof (Get_SmokeTestBuildAndRunWithSpecialCharacters_Data))] + public void SmokeTestBuildAndRunWithSpecialCharacters (string testName, AndroidRuntime runtime) { + const bool isRelease = true; + if (IgnoreUnsupportedConfiguration (runtime, release: isRelease)) { + return; + } + + // TODO: fix NativeAOT builds. Despite the .so library being preset in the apk (and named correctly) + // all the tests fail with one of: + // + // java.lang.UnsatisfiedLinkError: dlopen failed: library "libテスト.so" not found + // java.lang.UnsatisfiedLinkError: dlopen failed: library "lib中国.so" not found + // java.lang.UnsatisfiedLinkError: dlopen failed: library "lib随机生成器.so" not found + // + // It might be an issue with the Android shared libary loader or name encoding in the archive. It might + // be a good idea to limit .so names to ASCII. + if (runtime == AndroidRuntime.NativeAOT) { + Assert.Ignore ("NativeAOT doesn't work well with diacritics in the application library name"); + } + var rootPath = Path.Combine (Root, "temp", TestName); - var proj = new XamarinFormsAndroidApplicationProject () { + var proj = new XamarinFormsAndroidApplicationProject (packageName: PackageUtils.MakePackageName (runtime)) { ProjectName = testName, - IsRelease = true, + IsRelease = isRelease, }; + proj.SetRuntime (runtime); proj.SetAndroidSupportedAbis (DeviceAbi); proj.SetDefaultTargetDevice (); using (var builder = CreateApkBuilder (Path.Combine (rootPath, proj.ProjectName))){ From b837f80734e419907d819edea0ca98f9ddb95119 Mon Sep 17 00:00:00 2001 From: Marek Habersack Date: Mon, 8 Dec 2025 15:10:16 +0100 Subject: [PATCH 08/25] InstallAndRunTests.CustomLinkDescriptionPreserve updated, broken on NAOT too --- .../Tests/InstallAndRunTests.cs | 25 ++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/tests/MSBuildDeviceIntegration/Tests/InstallAndRunTests.cs b/tests/MSBuildDeviceIntegration/Tests/InstallAndRunTests.cs index b1490328e2f..da5b6e6c857 100644 --- a/tests/MSBuildDeviceIntegration/Tests/InstallAndRunTests.cs +++ b/tests/MSBuildDeviceIntegration/Tests/InstallAndRunTests.cs @@ -415,10 +415,28 @@ public void SmokeTestBuildAndRunWithSpecialCharacters (string testName, AndroidR [Test] public void CustomLinkDescriptionPreserve ( [Values (AndroidLinkMode.SdkOnly, AndroidLinkMode.Full)] AndroidLinkMode linkMode, - [Values (AndroidRuntime.MonoVM)] AndroidRuntime runtime + [Values] AndroidRuntime runtime ) { + const bool isRelease = true; + if (IgnoreUnsupportedConfiguration (runtime, release: isRelease)) { + return; + } + + if (runtime == AndroidRuntime.CoreCLR) { + Assert.Ignore ("Currently broken on CoreCLR"); + } + + // TODO: NativeAOT perhaps should work here (ignoring all the MonoAOT settings?), but for now it fails with + // + // Microsoft.NET.Sdk.FrameworkReferenceResolution.targets(120,5): error NETSDK1207: Ahead-of-time compilation is not supported for the target framework. + // + if (runtime == AndroidRuntime.NativeAOT) { + Assert.Ignore ("NativeAOT is currently broken here"); + } + var lib1 = new XamarinAndroidLibraryProject () { + IsRelease = isRelease, ProjectName = "Library1", Sources = { new BuildItem.Source ("SomeClass.cs") { @@ -456,6 +474,7 @@ public class LinkModeFullClass { lib1.SetRuntime (runtime); var lib2 = new DotNetStandard { + IsRelease = isRelease, ProjectName = "LinkTestLib", Sdk = "Microsoft.NET.Sdk", TargetFramework = "netstandard2.0", @@ -482,8 +501,8 @@ public class LinkModeFullClass { }; lib2.SetRuntime (runtime); - proj = new XamarinFormsAndroidApplicationProject () { - IsRelease = true, + proj = new XamarinFormsAndroidApplicationProject (packageName: PackageUtils.MakePackageName (runtime)) { + IsRelease = isRelease, AndroidLinkModeRelease = linkMode, References = { new BuildItem ("ProjectReference", "..\\Library1\\Library1.csproj"), From 161c584e373a1bcfe9bad9d78547fbd84ad30ce6 Mon Sep 17 00:00:00 2001 From: Marek Habersack Date: Mon, 8 Dec 2025 16:12:38 +0100 Subject: [PATCH 09/25] InstallAndRunTests.JsonDeserializationCreatesJavaHandle works --- .../MSBuildDeviceIntegration/Tests/InstallAndRunTests.cs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/tests/MSBuildDeviceIntegration/Tests/InstallAndRunTests.cs b/tests/MSBuildDeviceIntegration/Tests/InstallAndRunTests.cs index da5b6e6c857..803d406f7b8 100644 --- a/tests/MSBuildDeviceIntegration/Tests/InstallAndRunTests.cs +++ b/tests/MSBuildDeviceIntegration/Tests/InstallAndRunTests.cs @@ -581,11 +581,15 @@ string getResource (string name) } [Test] - public void JsonDeserializationCreatesJavaHandle ([Values (false, true)] bool isRelease) + public void JsonDeserializationCreatesJavaHandle ([Values] bool isRelease, [Values] AndroidRuntime runtime) { - proj = new XamarinAndroidApplicationProject () { + if (IgnoreUnsupportedConfiguration (runtime, release: isRelease)) { + return; + } + proj = new XamarinAndroidApplicationProject (packageName: PackageUtils.MakePackageName (runtime)) { IsRelease = isRelease, }; + proj.SetRuntime (runtime); // error SYSLIB0011: 'BinaryFormatter.Serialize(Stream, object)' is obsolete: 'BinaryFormatter serialization is obsolete and should not be used. See https://aka.ms/binaryformatter for more information.' proj.SetProperty ("NoWarn", "SYSLIB0011"); From 88081d3b57586d213c6b2238e9461875aabd853f Mon Sep 17 00:00:00 2001 From: Marek Habersack Date: Mon, 8 Dec 2025 16:16:35 +0100 Subject: [PATCH 10/25] InstallAndRunTests.RunWithInterpreterEnabled updated --- .../Tests/InstallAndRunTests.cs | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/tests/MSBuildDeviceIntegration/Tests/InstallAndRunTests.cs b/tests/MSBuildDeviceIntegration/Tests/InstallAndRunTests.cs index 803d406f7b8..917c2b1040b 100644 --- a/tests/MSBuildDeviceIntegration/Tests/InstallAndRunTests.cs +++ b/tests/MSBuildDeviceIntegration/Tests/InstallAndRunTests.cs @@ -677,14 +677,22 @@ public override Type BindToType (string assemblyName, string typeName) } [Test] - public void RunWithInterpreterEnabled ([Values (false, true)] bool isRelease) + public void RunWithInterpreterEnabled ([Values] bool isRelease, [Values] AndroidRuntime runtime) { - proj = new XamarinAndroidApplicationProject () { + if (IgnoreUnsupportedConfiguration (runtime, release: isRelease)) { + return; + } + + // MonoVM-only test, for now (until CoreCLR has interpreter we can use) + if (runtime != AndroidRuntime.MonoVM) { + Assert.Ignore ("MonoVM-only test for the moment"); + } + + proj = new XamarinAndroidApplicationProject (packageName: PackageUtils.MakePackageName (runtime)) { IsRelease = isRelease, AotAssemblies = false, // Release defaults to Profiled AOT for .NET 6 }; - // MonoVM-only test - proj.SetRuntime (Android.Tasks.AndroidRuntime.MonoVM); + proj.SetRuntime (runtime); var abis = new string[] { "armeabi-v7a", "arm64-v8a", "x86", "x86_64" }; proj.SetAndroidSupportedAbis (abis); proj.SetProperty (proj.CommonProperties, "UseInterpreter", "True"); From dede04d7456c2663ffdeac5b52bdd8e64439d546 Mon Sep 17 00:00:00 2001 From: Marek Habersack Date: Mon, 8 Dec 2025 16:20:36 +0100 Subject: [PATCH 11/25] InstallAndRunTests.SingleProject_ApplicationId updated --- .../Tests/InstallAndRunTests.cs | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/tests/MSBuildDeviceIntegration/Tests/InstallAndRunTests.cs b/tests/MSBuildDeviceIntegration/Tests/InstallAndRunTests.cs index 917c2b1040b..19304bd6ca6 100644 --- a/tests/MSBuildDeviceIntegration/Tests/InstallAndRunTests.cs +++ b/tests/MSBuildDeviceIntegration/Tests/InstallAndRunTests.cs @@ -764,11 +764,19 @@ bool SeenFailedToLoad (string line) } [Test] - public void SingleProject_ApplicationId ([Values (false, true)] bool testOnly) + public void SingleProject_ApplicationId ([Values] bool testOnly, [Values] AndroidRuntime runtime) { + bool isRelease = runtime == AndroidRuntime.NativeAOT; + if (IgnoreUnsupportedConfiguration (runtime, release: isRelease)) { + return; + } + AssertCommercialBuild (); - proj = new XamarinAndroidApplicationProject (); + proj = new XamarinAndroidApplicationProject (packageName: PackageUtils.MakePackageName (runtime)) { + IsRelease = isRelease, + }; + proj.SetRuntime (runtime); proj.SetProperty ("ApplicationId", "com.i.should.get.overridden.by.the.manifest"); if (testOnly) proj.AndroidManifest = proj.AndroidManifest.Replace (" Date: Tue, 9 Dec 2025 16:48:35 +0100 Subject: [PATCH 12/25] InstallAndRunTests.AppWithStyleableUsageRuns updated --- .../Tests/InstallAndRunTests.cs | 52 +++++++++++++++---- 1 file changed, 41 insertions(+), 11 deletions(-) diff --git a/tests/MSBuildDeviceIntegration/Tests/InstallAndRunTests.cs b/tests/MSBuildDeviceIntegration/Tests/InstallAndRunTests.cs index 19304bd6ca6..c18c1be66c1 100644 --- a/tests/MSBuildDeviceIntegration/Tests/InstallAndRunTests.cs +++ b/tests/MSBuildDeviceIntegration/Tests/InstallAndRunTests.cs @@ -792,22 +792,50 @@ public void SingleProject_ApplicationId ([Values] bool testOnly, [Values] Androi } [Test] - public void AppWithStyleableUsageRuns ([Values (true, false)] bool useCLR, [Values (true, false)] bool isRelease, - [Values (true, false)] bool linkResources, [Values (true, false)] bool useStringTypeMaps) + public void AppWithStyleableUsageRuns ([Values] bool isRelease, [Values] bool linkResources, [Values] bool useStringTypeMaps, [Values] AndroidRuntime runtime) { + if (IgnoreUnsupportedConfiguration (runtime, release: isRelease)) { + return; + } + // Not all combinations are valid, ignore those that aren't - if (!useCLR && useStringTypeMaps) { - Assert.Ignore ("String-based typemaps mode is used only in CoreCLR apps"); + if (runtime == AndroidRuntime.MonoVM && useStringTypeMaps) { + Assert.Ignore ("String-based typemaps mode is used only in CoreCLR and NativeAOT apps"); } - if (useCLR && isRelease && useStringTypeMaps) { + if (runtime != AndroidRuntime.MonoVM && isRelease && useStringTypeMaps) { Assert.Ignore ("String-based typemaps mode is available only in Debug CoreCLR builds"); } + // TODO: fix this for NativeAOT + if (runtime == AndroidRuntime.NativeAOT && isRelease && !useStringTypeMaps) { + // This configuration currently fails with a long stack trace, the gist of it is: + // + // AndroidRuntime: java.lang.RuntimeException: Unable to start activity ComponentInfo{com.xamarin.appwithstyleableusageruns_nativeaot/com.xamarin.appwithstyleableusageruns_nativeaot.MainActivity} + // AndroidRuntime: Caused by: android.view.InflateException: Binary XML file line #1 in com.xamarin.appwithstyleableusageruns_nativeaot:layout/main: Binary XML file line #1 in com.xamarin.appwithstyleableusageruns_nativeaot:layout/main: Error inflating class crc64f75eeacfa0ca1368.MyLayout + // AndroidRuntime: Caused by: android.view.InflateException: Binary XML file line #1 in com.xamarin.appwithstyleableusageruns_nativeaot:layout/main: Error inflating class crc64f75eeacfa0ca1368.MyLayout + // AndroidRuntime: Caused by: java.lang.reflect.InvocationTargetException + // AndroidRuntime: Caused by: net.dot.jni.internal.JavaProxyThrowable: System.NotSupportedException: Could not activate { PeerReference=0x7fe9706698/I IdentityHashCode=0xd12aeee Java.Type=crc64f75eeacfa0ca1368/MyLayout } for managed type 'UnnamedProject.MyLayout'. + // AndroidRuntime: ---> System.Reflection.TargetInvocationException: Arg_TargetInvocationException + // AndroidRuntime: ---> System.IO.FileNotFoundException: IO_FileNotFound_FileName, _Microsoft.Android.Resource.Designer + // AndroidRuntime: IO_FileName_Name, _Microsoft.Android.Resource.Designer + // DOTNET : FATAL UNHANDLED EXCEPTION: Java.Lang.Exception: Unable to start activity ComponentInfo{com.xamarin.appwithstyleableusageruns_nativeaot/com.xamarin.appwithstyleableusageruns_nativeaot.MainActivity} + // DOTNET : ---> Java.Lang.Exception: Binary XML file line #1 in com.xamarin.appwithstyleableusageruns_nativeaot:layout/main: Binary XML file line #1 in com.xamarin.appwithstyleableusageruns_nativeaot:layout/main: Error inflating class crc64f75eeacfa0ca1368.MyLayout + // DOTNET : ---> Java.Lang.Exception: Binary XML file line #1 in com.xamarin.appwithstyleableusageruns_nativeaot:layout/main: Error inflating class crc64f75eeacfa0ca1368.MyLayout + // DOTNET : ---> Java.Lang.ReflectiveOperationException: Exception_WasThrown, Java.Lang.ReflectiveOperationException + // DOTNET : ---> System.NotSupportedException: Could not activate { PeerReference=0x7fe9706698/I IdentityHashCode=0xd12aeee Java.Type=crc64f75eeacfa0ca1368/MyLayout } for managed type 'UnnamedProject.MyLayout'. + // DOTNET : ---> System.Reflection.TargetInvocationException: Arg_TargetInvocationException + // DOTNET : ---> System.IO + // eruns_nativeaot: No implementation found for void mono.android.Runtime.propagateUncaughtException(java.lang.Thread, java.lang.Throwable) (tried Java_mono_android_Runtime_propagateUncaughtException and Java_mono_android_Runtime_propagateUncaughtException__Ljava_lang_Thread_2Ljava_lang_Throwable_2) - is the library loaded, e.g. System.loadLibrary? + Assert.Ignore ("NativeAOT is broken without string-based typemaps"); + } + var rootPath = Path.Combine (Root, "temp", TestName); var lib = new XamarinAndroidLibraryProject () { + IsRelease = isRelease, ProjectName = "Styleable.Library" }; + lib.SetRuntime (runtime); lib.AndroidResources.Add (new AndroidItem.AndroidResource ("Resources\\values\\styleables.xml") { TextContent = () => @" @@ -849,10 +877,10 @@ public MyLibraryLayout (Android.Content.Context context, Android.Util.IAttribute }" }); - proj = new XamarinAndroidApplicationProject () { + proj = new XamarinAndroidApplicationProject (packageName: PackageUtils.MakePackageName (runtime)) { IsRelease = isRelease, }; - proj.SetProperty ("UseMonoRuntime", useCLR ? "false" : "true"); + proj.SetRuntime (runtime); proj.AddReference (lib); proj.AndroidResources.Add (new AndroidItem.AndroidResource ("Resources\\values\\styleables.xml") { @@ -890,9 +918,11 @@ public MyLayout (Android.Content.Context context, Android.Util.IAttributeSet att } "); - string[] abis = useCLR switch { - true => new string [] { "arm64-v8a", "x86_64" }, - false => new string [] { "armeabi-v7a", "arm64-v8a", "x86", "x86_64" }, + string[] abis = runtime switch { + AndroidRuntime.CoreCLR => new string [] { "arm64-v8a", "x86_64" }, + AndroidRuntime.NativeAOT => new string [] { "arm64-v8a", "x86_64" }, + AndroidRuntime.MonoVM => new string [] { "armeabi-v7a", "arm64-v8a", "x86", "x86_64" }, + _ => throw new NotSupportedException ($"Unsupported runtime {runtime}") }; proj.SetAndroidSupportedAbis (abis); @@ -903,7 +933,7 @@ public MyLayout (Android.Content.Context context, Android.Util.IAttributeSet att Assert.IsTrue (builder.Install (proj), "Install should have succeeded."); Dictionary? environmentVariables = null; - if (useCLR && !isRelease && useStringTypeMaps) { + if (runtime == AndroidRuntime.CoreCLR && !isRelease && useStringTypeMaps) { // The variable must have content to enable string-based typemaps environmentVariables = new (StringComparer.Ordinal) { {"CI_TYPEMAP_DEBUG_USE_STRINGS", "yes"} From 089d9a720b1b65c02ae0fe7a03c295b2d4b7cffb Mon Sep 17 00:00:00 2001 From: Marek Habersack Date: Tue, 9 Dec 2025 17:23:25 +0100 Subject: [PATCH 13/25] InstallAndRunTests.CheckXamarinFormsAppDeploysAndAButtonWorks broken locally It might work on CI, we'll see --- .../Tests/InstallAndRunTests.cs | 23 ++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/tests/MSBuildDeviceIntegration/Tests/InstallAndRunTests.cs b/tests/MSBuildDeviceIntegration/Tests/InstallAndRunTests.cs index c18c1be66c1..9a9cb3507d1 100644 --- a/tests/MSBuildDeviceIntegration/Tests/InstallAndRunTests.cs +++ b/tests/MSBuildDeviceIntegration/Tests/InstallAndRunTests.cs @@ -948,16 +948,33 @@ public MyLayout (Android.Content.Context context, Android.Util.IAttributeSet att } [Test] - public void CheckXamarinFormsAppDeploysAndAButtonWorks () + public void CheckXamarinFormsAppDeploysAndAButtonWorks ([Values] AndroidRuntime runtime) { - var proj = new XamarinFormsAndroidApplicationProject (); + bool isRelease = runtime == AndroidRuntime.NativeAOT; + if (IgnoreUnsupportedConfiguration (runtime, release: isRelease)) { + return; + } + + // TODO: fix for NativeAOT. Currently fails with: + // + // DOTNET : FATAL UNHANDLED EXCEPTION: System.InvalidCastException: Unable to convert instance of type 'AndroidX.AppCompat.Widget.AppCompatImageButton' to type 'AndroidX.AppCompat.Widget.Toolbar'. + if (runtime == AndroidRuntime.NativeAOT) { + Assert.Ignore ("NativeAOT type mapping fails"); + } + + string packageName = PackageUtils.MakePackageName (runtime); + var proj = new XamarinFormsAndroidApplicationProject (packageName: packageName) { + IsRelease = isRelease, + }; + proj.SetRuntime (runtime); proj.SetAndroidSupportedAbis (DeviceAbi); - var builder = CreateApkBuilder (); + var builder = CreateApkBuilder (packageName: packageName); Assert.IsTrue (builder.Build (proj), "Build should have succeeded."); builder.BuildLogFile = "install.log"; Assert.IsTrue (builder.Install (proj), "Install should have succeeded."); + ClearAdbLogcat (); AdbStartActivity ($"{proj.PackageName}/{proj.JavaPackageName}.MainActivity"); WaitForActivityToStart (proj.PackageName, "MainActivity", Path.Combine (Root, builder.ProjectDirectory, "startup-logcat.log"), 15); From fe3cfe36828bc3560dbd678221cc6d3920cc9b1c Mon Sep 17 00:00:00 2001 From: Marek Habersack Date: Tue, 9 Dec 2025 17:50:34 +0100 Subject: [PATCH 14/25] InstallAndRunTests.SkiaSharpCanvasBasedAppRuns works --- .../Tests/InstallAndRunTests.cs | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/tests/MSBuildDeviceIntegration/Tests/InstallAndRunTests.cs b/tests/MSBuildDeviceIntegration/Tests/InstallAndRunTests.cs index 9a9cb3507d1..a28b51e74cc 100644 --- a/tests/MSBuildDeviceIntegration/Tests/InstallAndRunTests.cs +++ b/tests/MSBuildDeviceIntegration/Tests/InstallAndRunTests.cs @@ -987,11 +987,14 @@ public void CheckXamarinFormsAppDeploysAndAButtonWorks ([Values] AndroidRuntime } [Test] - public void SkiaSharpCanvasBasedAppRuns ([Values (true, false)] bool isRelease, [Values (true, false)] bool addResource) + public void SkiaSharpCanvasBasedAppRuns ([Values] bool isRelease, [Values] bool addResource, [Values] AndroidRuntime runtime) { - var app = new XamarinAndroidApplicationProject () { + if (IgnoreUnsupportedConfiguration (runtime, release: isRelease)) { + return; + } + + var app = new XamarinAndroidApplicationProject (packageName: $"SkiaSharpCanvasTest_{runtime.ToString ().ToLowerInvariant ()}") { IsRelease = isRelease, - PackageName = "Xamarin.SkiaSharpCanvasTest", PackageReferences = { KnownPackages.SkiaSharp, KnownPackages.SkiaSharp_Views, @@ -999,6 +1002,7 @@ public void SkiaSharpCanvasBasedAppRuns ([Values (true, false)] bool isRelease, KnownPackages.AndroidXAppCompatResources, }, }; + app.SetRuntime (runtime); app.AndroidResources.Add (new AndroidItem.AndroidResource ("Resources\\values\\styles.xml") { TextContent = () => @"