From 72b9fc1d24da50cf93588c94c3e7b17deac501be Mon Sep 17 00:00:00 2001 From: Jonathan Peppers Date: Fri, 16 Jan 2026 11:16:40 -0600 Subject: [PATCH 01/10] [hot reload] implement `DeployHotReloadAgentConfiguration` target Context: https://github.com/dotnet/sdk/issues/52492 Context: https://github.com/dotnet/runtime/blob/79609d7dbef01231b0694a356de1d4e5618785cd/src/libraries/System.Private.CoreLib/src/System/StartupHookProvider.cs#L32 Context: https://github.com/dotnet/runtime/blob/79609d7dbef01231b0694a356de1d4e5618785cd/src/mono/mono/metadata/object.c#L8137-L8140 Context: b2332ca7 Added a new `DeployHotReloadAgentConfiguration` MSBuild target that `dotnet-watch` can use to configure Hot Reload for Android apps. Notes on runtimes: * MonoVM currently passes `string.Empty` to `ProcessStartupHooks` and relies on reading `STARTUP_HOOKS` from `AppContext`. * To fix CoreCLR, we can read `DOTNET_STARTUP_HOOKS` from environment variables, and pass to `ProcessStartupHooks`. * NativeAOT likely works as-is. I added/updated tests to verify these changes. --- .../Android.Runtime/JNIEnvInit.cs | 8 +- .../Microsoft.Android.Sdk.After.targets | 1 + .../Microsoft.Android.Sdk.HotReload.targets | 84 +++++++++++++++++++ .../Tests/InstallAndRunTests.cs | 81 ++++++++++++++++++ .../Mono.Android.NET-Tests.csproj | 2 +- 5 files changed, 172 insertions(+), 4 deletions(-) create mode 100644 src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.HotReload.targets diff --git a/src/Mono.Android/Android.Runtime/JNIEnvInit.cs b/src/Mono.Android/Android.Runtime/JNIEnvInit.cs index b8aa2e2507d..71b370a3cee 100644 --- a/src/Mono.Android/Android.Runtime/JNIEnvInit.cs +++ b/src/Mono.Android/Android.Runtime/JNIEnvInit.cs @@ -204,9 +204,11 @@ static void RunStartupHooks () return; } - // Pass empty string for diagnosticStartupHooks parameter - // The method will read STARTUP_HOOKS from AppContext internally - method.Invoke (null, [ "" ]); + // ProcessStartupHooks accepts startup hooks directly via parameter. + // It will also read STARTUP_HOOKS from AppContext internally. + // Pass DOTNET_STARTUP_HOOKS env var value so it works without needing AppContext setup. + string? startupHooks = Environment.GetEnvironmentVariable ("DOTNET_STARTUP_HOOKS"); + method.Invoke (null, [ startupHooks ?? "" ]); } static void SetSynchronizationContext () => diff --git a/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.After.targets b/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.After.targets index 9cb93fb2e06..01a64d12687 100644 --- a/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.After.targets +++ b/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.After.targets @@ -33,4 +33,5 @@ This file is imported *after* the Microsoft.NET.Sdk/Sdk.targets. + diff --git a/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.HotReload.targets b/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.HotReload.targets new file mode 100644 index 00000000000..9cf0e8469ed --- /dev/null +++ b/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.HotReload.targets @@ -0,0 +1,84 @@ + + + + + + + true + + + + + + + <_HotReloadAgentAssemblyName>$([System.IO.Path]::GetFileNameWithoutExtension('$(DotNetHotReloadAgentStartupHook)')) + + + + + + + + + + + + + + + <_HotReloadEnvironment Include="DOTNET_STARTUP_HOOKS=$(_HotReloadAgentAssemblyName)" /> + + + + + <_HotReloadEnvironment Include="$(DotNetHotReloadAgentEnvironment)" /> + + + + + + + + + + + + + + + + diff --git a/tests/MSBuildDeviceIntegration/Tests/InstallAndRunTests.cs b/tests/MSBuildDeviceIntegration/Tests/InstallAndRunTests.cs index 5e4c4a5e1b8..029d9afe09e 100644 --- a/tests/MSBuildDeviceIntegration/Tests/InstallAndRunTests.cs +++ b/tests/MSBuildDeviceIntegration/Tests/InstallAndRunTests.cs @@ -1582,5 +1582,86 @@ public void AppStartsWithManagedMarshalMethodsLookupEnabled () Path.Combine (Root, builder.ProjectDirectory, "logcat.log"), 30); Assert.IsTrue (didLaunch, "Activity should have started."); } + + [Test] + public void DeployHotReloadAgentConfiguration () + { + // Create a simple "startup hook" assembly that sets an env var we can check + var startupHookCode = @" +using System; + +internal static class StartupHook +{ + public static void Initialize () + { + Console.WriteLine (""HOTRELOAD_TEST_HOOK_INITIALIZED=true""); + } +} +"; + var proj = new XamarinAndroidApplicationProject { + ProjectName = nameof (DeployHotReloadAgentConfiguration), + IsRelease = false, + }; + proj.MainActivity = proj.DefaultMainActivity.Replace ("//${AFTER_ONCREATE}", @" + Console.WriteLine (""DOTNET_STARTUP_HOOKS="" + Environment.GetEnvironmentVariable(""DOTNET_STARTUP_HOOKS"")); + Console.WriteLine (""HOTRELOAD_TEST_VAR="" + Environment.GetEnvironmentVariable(""HOTRELOAD_TEST_VAR"")); + Console.WriteLine (""ANOTHER_VAR="" + Environment.GetEnvironmentVariable(""ANOTHER_VAR"")); +"); + proj.Sources.Add (new BuildItem.Source ("StartupHook.cs") { TextContent = () => startupHookCode }); + + using var builder = CreateApkBuilder (); + builder.Save (proj); + + var projectDirectory = Path.Combine (Root, builder.ProjectDirectory); + var dotnet = new DotNetCLI (Path.Combine (projectDirectory, proj.ProjectFilePath)); + + // Build normally first + Assert.IsTrue (dotnet.Build (), "`dotnet build` should succeed"); + + // Simulate what dotnet-watch/IDE would do: set the hot reload properties and run the target + var hotReloadProperties = new [] { + "DotNetHotReloadAgentStartupHook=StartupHook", + "DotNetHotReloadAgentEnvironment=HOTRELOAD_TEST_VAR=TestValue123;ANOTHER_VAR=AnotherValue456", + }; + Assert.IsTrue (dotnet.Build ("DeployHotReloadAgentConfiguration", hotReloadProperties), + "`dotnet build -t:DeployHotReloadAgentConfiguration` should succeed"); + + // Launch the app using adb + ClearAdbLogcat (); + var result = AdbStartActivity ($"{proj.PackageName}/{proj.JavaPackageName}.MainActivity"); + Assert.IsTrue (result.Contains ("Starting: Intent"), $"Activity should have launched. adb output:\n{result}"); + + bool didLaunch = WaitForActivityToStart (proj.PackageName, "MainActivity", + Path.Combine (projectDirectory, "logcat.log"), 30); + Assert.IsTrue (didLaunch, "Activity should have started."); + + var logcatOutput = File.ReadAllText (Path.Combine (projectDirectory, "logcat.log")); + + // Verify the startup hook was set via DOTNET_STARTUP_HOOKS + StringAssert.Contains ( + "DOTNET_STARTUP_HOOKS=StartupHook", + logcatOutput, + "DOTNET_STARTUP_HOOKS should be set to StartupHook" + ); + + // Verify the startup hook was called + StringAssert.Contains ( + "HOTRELOAD_TEST_HOOK_INITIALIZED=true", + logcatOutput, + "StartupHook.Initialize() should have been called" + ); + + // Verify the additional env vars from DotNetHotReloadAgentEnvironment were set + StringAssert.Contains ( + "HOTRELOAD_TEST_VAR=TestValue123", + logcatOutput, + "HOTRELOAD_TEST_VAR should be set from DotNetHotReloadAgentEnvironment" + ); + StringAssert.Contains ( + "ANOTHER_VAR=AnotherValue456", + logcatOutput, + "ANOTHER_VAR should be set from DotNetHotReloadAgentEnvironment" + ); + } } } diff --git a/tests/Mono.Android-Tests/Mono.Android-Tests/Mono.Android.NET-Tests.csproj b/tests/Mono.Android-Tests/Mono.Android-Tests/Mono.Android.NET-Tests.csproj index 8047c3713ef..1689adbb290 100644 --- a/tests/Mono.Android-Tests/Mono.Android-Tests/Mono.Android.NET-Tests.csproj +++ b/tests/Mono.Android-Tests/Mono.Android-Tests/Mono.Android.NET-Tests.csproj @@ -231,7 +231,7 @@ - + From 5a5fc6742c7e318fe05102e3247d8569260961ce Mon Sep 17 00:00:00 2001 From: Jonathan Peppers Date: Fri, 16 Jan 2026 12:37:58 -0600 Subject: [PATCH 02/10] Update InstallAndRunTests.cs --- tests/MSBuildDeviceIntegration/Tests/InstallAndRunTests.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/MSBuildDeviceIntegration/Tests/InstallAndRunTests.cs b/tests/MSBuildDeviceIntegration/Tests/InstallAndRunTests.cs index 029d9afe09e..937c8754cf9 100644 --- a/tests/MSBuildDeviceIntegration/Tests/InstallAndRunTests.cs +++ b/tests/MSBuildDeviceIntegration/Tests/InstallAndRunTests.cs @@ -1623,7 +1623,7 @@ public static void Initialize () "DotNetHotReloadAgentStartupHook=StartupHook", "DotNetHotReloadAgentEnvironment=HOTRELOAD_TEST_VAR=TestValue123;ANOTHER_VAR=AnotherValue456", }; - Assert.IsTrue (dotnet.Build ("DeployHotReloadAgentConfiguration", hotReloadProperties), + Assert.IsTrue (dotnet.Build (target: "DeployHotReloadAgentConfiguration", parameters: hotReloadProperties), "`dotnet build -t:DeployHotReloadAgentConfiguration` should succeed"); // Launch the app using adb From 38de42f9354716163d2ca09c9fe5415080dfabfc Mon Sep 17 00:00:00 2001 From: Jonathan Peppers Date: Fri, 16 Jan 2026 16:18:17 -0600 Subject: [PATCH 03/10] Update InstallAndRunTests.cs --- tests/MSBuildDeviceIntegration/Tests/InstallAndRunTests.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/MSBuildDeviceIntegration/Tests/InstallAndRunTests.cs b/tests/MSBuildDeviceIntegration/Tests/InstallAndRunTests.cs index 937c8754cf9..6f7a07bff42 100644 --- a/tests/MSBuildDeviceIntegration/Tests/InstallAndRunTests.cs +++ b/tests/MSBuildDeviceIntegration/Tests/InstallAndRunTests.cs @@ -1602,6 +1602,7 @@ public static void Initialize () ProjectName = nameof (DeployHotReloadAgentConfiguration), IsRelease = false, }; + proj.SetRuntime (AndroidRuntime.CoreCLR); proj.MainActivity = proj.DefaultMainActivity.Replace ("//${AFTER_ONCREATE}", @" Console.WriteLine (""DOTNET_STARTUP_HOOKS="" + Environment.GetEnvironmentVariable(""DOTNET_STARTUP_HOOKS"")); Console.WriteLine (""HOTRELOAD_TEST_VAR="" + Environment.GetEnvironmentVariable(""HOTRELOAD_TEST_VAR"")); From 8aa3cd7d5a82d42219f4671f67966a0ffe0102cc Mon Sep 17 00:00:00 2001 From: Jonathan Peppers Date: Fri, 16 Jan 2026 16:24:34 -0600 Subject: [PATCH 04/10] Update StartupHookTest.cs --- .../Mono.Android-Tests/System/StartupHookTest.cs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/tests/Mono.Android-Tests/Mono.Android-Tests/System/StartupHookTest.cs b/tests/Mono.Android-Tests/Mono.Android-Tests/System/StartupHookTest.cs index f58bf1b48ab..a2e2602b853 100644 --- a/tests/Mono.Android-Tests/Mono.Android-Tests/System/StartupHookTest.cs +++ b/tests/Mono.Android-Tests/Mono.Android-Tests/System/StartupHookTest.cs @@ -7,6 +7,13 @@ namespace SystemTests [TestFixture] public class StartupHookTest { + [Test] + public void StartupHookSupportFeatureFlagIsEnabled () + { + // NOTE: this is set to true in tests\Mono.Android-Tests\Mono.Android-Tests\Mono.Android.NET-Tests.csproj + Assert.IsTrue (Microsoft.Android.Runtime.RuntimeFeature.StartupHookSupport, "RuntimeFeature.StartupHookSupport should be true"); + } + [Test] public void IsInitialized () { From ec616620509089914a1dcc4d8b37e1d8906fa44c Mon Sep 17 00:00:00 2001 From: Jonathan Peppers Date: Tue, 20 Jan 2026 16:34:54 -0600 Subject: [PATCH 05/10] @(DotNetHotReloadAgentEnvironment) is item group --- .../Microsoft.Android.Sdk.HotReload.targets | 12 +++++----- .../Tests/InstallAndRunTests.cs | 22 ++++++++++++++----- 2 files changed, 22 insertions(+), 12 deletions(-) diff --git a/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.HotReload.targets b/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.HotReload.targets index 9cf0e8469ed..b092912c2ef 100644 --- a/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.HotReload.targets +++ b/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.HotReload.targets @@ -47,9 +47,9 @@ See: https://github.com/dotnet/sdk/issues/52492 <_HotReloadEnvironment Include="DOTNET_STARTUP_HOOKS=$(_HotReloadAgentAssemblyName)" /> - - - <_HotReloadEnvironment Include="$(DotNetHotReloadAgentEnvironment)" /> + + + <_HotReloadEnvironment Include="@(DotNetHotReloadAgentEnvironment->'%(Identity)=%(Value)')" /> --> diff --git a/tests/MSBuildDeviceIntegration/Tests/InstallAndRunTests.cs b/tests/MSBuildDeviceIntegration/Tests/InstallAndRunTests.cs index 6f7a07bff42..c926852ae8a 100644 --- a/tests/MSBuildDeviceIntegration/Tests/InstallAndRunTests.cs +++ b/tests/MSBuildDeviceIntegration/Tests/InstallAndRunTests.cs @@ -1601,6 +1601,20 @@ public static void Initialize () var proj = new XamarinAndroidApplicationProject { ProjectName = nameof (DeployHotReloadAgentConfiguration), IsRelease = false, + Imports = { + // Add a .targets file that simulates what dotnet-watch/IDE would inject + new Import (() => "HotReload.targets") { + TextContent = () => @" + + StartupHook + + + + + +" + }, + } }; proj.SetRuntime (AndroidRuntime.CoreCLR); proj.MainActivity = proj.DefaultMainActivity.Replace ("//${AFTER_ONCREATE}", @" @@ -1619,12 +1633,8 @@ public static void Initialize () // Build normally first Assert.IsTrue (dotnet.Build (), "`dotnet build` should succeed"); - // Simulate what dotnet-watch/IDE would do: set the hot reload properties and run the target - var hotReloadProperties = new [] { - "DotNetHotReloadAgentStartupHook=StartupHook", - "DotNetHotReloadAgentEnvironment=HOTRELOAD_TEST_VAR=TestValue123;ANOTHER_VAR=AnotherValue456", - }; - Assert.IsTrue (dotnet.Build (target: "DeployHotReloadAgentConfiguration", parameters: hotReloadProperties), + // Run the DeployHotReloadAgentConfiguration target (hot reload properties come from HotReload.targets) + Assert.IsTrue (dotnet.Build (target: "DeployHotReloadAgentConfiguration"), "`dotnet build -t:DeployHotReloadAgentConfiguration` should succeed"); // Launch the app using adb From 081426d54f9425ae8254ecde0dd6f5dcf7b87c4c Mon Sep 17 00:00:00 2001 From: Jonathan Peppers Date: Tue, 20 Jan 2026 16:39:49 -0600 Subject: [PATCH 06/10] Fix DeployHotReloadAgentConfiguration test --- .../Tests/InstallAndRunTests.cs | 24 ++++++++++++++----- 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/tests/MSBuildDeviceIntegration/Tests/InstallAndRunTests.cs b/tests/MSBuildDeviceIntegration/Tests/InstallAndRunTests.cs index c926852ae8a..45723aa95e7 100644 --- a/tests/MSBuildDeviceIntegration/Tests/InstallAndRunTests.cs +++ b/tests/MSBuildDeviceIntegration/Tests/InstallAndRunTests.cs @@ -1586,8 +1586,12 @@ public void AppStartsWithManagedMarshalMethodsLookupEnabled () [Test] public void DeployHotReloadAgentConfiguration () { - // Create a simple "startup hook" assembly that sets an env var we can check - var startupHookCode = @" + // Create a library project that contains the startup hook + var startupHookLib = new XamarinAndroidLibraryProject { + ProjectName = "StartupHook", + Sources = { + new BuildItem.Source ("StartupHook.cs") { + TextContent = () => @" using System; internal static class StartupHook @@ -1597,7 +1601,11 @@ public static void Initialize () Console.WriteLine (""HOTRELOAD_TEST_HOOK_INITIALIZED=true""); } } -"; +" + } + } + }; + var proj = new XamarinAndroidApplicationProject { ProjectName = nameof (DeployHotReloadAgentConfiguration), IsRelease = false, @@ -1617,17 +1625,21 @@ public static void Initialize () } }; proj.SetRuntime (AndroidRuntime.CoreCLR); + proj.AddReference (startupHookLib); proj.MainActivity = proj.DefaultMainActivity.Replace ("//${AFTER_ONCREATE}", @" Console.WriteLine (""DOTNET_STARTUP_HOOKS="" + Environment.GetEnvironmentVariable(""DOTNET_STARTUP_HOOKS"")); Console.WriteLine (""HOTRELOAD_TEST_VAR="" + Environment.GetEnvironmentVariable(""HOTRELOAD_TEST_VAR"")); Console.WriteLine (""ANOTHER_VAR="" + Environment.GetEnvironmentVariable(""ANOTHER_VAR"")); "); - proj.Sources.Add (new BuildItem.Source ("StartupHook.cs") { TextContent = () => startupHookCode }); - using var builder = CreateApkBuilder (); + var rootPath = Path.Combine (Root, "temp", TestName); + using var libBuilder = CreateDllBuilder (Path.Combine (rootPath, startupHookLib.ProjectName)); + Assert.IsTrue (libBuilder.Build (startupHookLib), "Library build should have succeeded."); + + using var builder = CreateApkBuilder (Path.Combine (rootPath, proj.ProjectName)); builder.Save (proj); - var projectDirectory = Path.Combine (Root, builder.ProjectDirectory); + var projectDirectory = Path.Combine (rootPath, proj.ProjectName); var dotnet = new DotNetCLI (Path.Combine (projectDirectory, proj.ProjectFilePath)); // Build normally first From e2964b44b775a250c9b82795bc81385d136593f8 Mon Sep 17 00:00:00 2001 From: Jonathan Peppers Date: Tue, 20 Jan 2026 16:45:00 -0600 Subject: [PATCH 07/10] Fix `$DOTNET_STARTUP_HOOKS` in tests --- .../Mono.Android-Tests/Mono.Android.NET-Tests.csproj | 5 +++-- tests/Mono.Android-Tests/Mono.Android-Tests/env.txt | 1 - tests/Mono.Android-Tests/Mono.Android-Tests/hotreload.env | 1 + 3 files changed, 4 insertions(+), 3 deletions(-) create mode 100644 tests/Mono.Android-Tests/Mono.Android-Tests/hotreload.env diff --git a/tests/Mono.Android-Tests/Mono.Android-Tests/Mono.Android.NET-Tests.csproj b/tests/Mono.Android-Tests/Mono.Android-Tests/Mono.Android.NET-Tests.csproj index 1689adbb290..d27f13ad188 100644 --- a/tests/Mono.Android-Tests/Mono.Android-Tests/Mono.Android.NET-Tests.csproj +++ b/tests/Mono.Android-Tests/Mono.Android-Tests/Mono.Android.NET-Tests.csproj @@ -52,11 +52,12 @@ true - + - + + diff --git a/tests/Mono.Android-Tests/Mono.Android-Tests/env.txt b/tests/Mono.Android-Tests/Mono.Android-Tests/env.txt index d3141692f53..cb897b79238 100644 --- a/tests/Mono.Android-Tests/Mono.Android-Tests/env.txt +++ b/tests/Mono.Android-Tests/Mono.Android-Tests/env.txt @@ -1,4 +1,3 @@ # Environment Variables and system properties # debug.mono.log=gref,default debug.mono.debug=1 -DOTNET_STARTUP_HOOKS=StartupHook diff --git a/tests/Mono.Android-Tests/Mono.Android-Tests/hotreload.env b/tests/Mono.Android-Tests/Mono.Android-Tests/hotreload.env new file mode 100644 index 00000000000..2c9605d07dd --- /dev/null +++ b/tests/Mono.Android-Tests/Mono.Android-Tests/hotreload.env @@ -0,0 +1 @@ +DOTNET_STARTUP_HOOKS=StartupHook From e7b1edf054b8dba65c055a1dc046158b15cef1f9 Mon Sep 17 00:00:00 2001 From: Jonathan Peppers Date: Wed, 21 Jan 2026 08:30:32 -0600 Subject: [PATCH 08/10] Rename project to MyStartupHook --- .../MSBuildDeviceIntegration/Tests/InstallAndRunTests.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/MSBuildDeviceIntegration/Tests/InstallAndRunTests.cs b/tests/MSBuildDeviceIntegration/Tests/InstallAndRunTests.cs index 45723aa95e7..8b29c9a2159 100644 --- a/tests/MSBuildDeviceIntegration/Tests/InstallAndRunTests.cs +++ b/tests/MSBuildDeviceIntegration/Tests/InstallAndRunTests.cs @@ -1588,7 +1588,7 @@ public void DeployHotReloadAgentConfiguration () { // Create a library project that contains the startup hook var startupHookLib = new XamarinAndroidLibraryProject { - ProjectName = "StartupHook", + ProjectName = "MyStartupHook", Sources = { new BuildItem.Source ("StartupHook.cs") { TextContent = () => @" @@ -1614,7 +1614,7 @@ public static void Initialize () new Import (() => "HotReload.targets") { TextContent = () => @" - StartupHook + MyStartupHook @@ -1662,9 +1662,9 @@ public static void Initialize () // Verify the startup hook was set via DOTNET_STARTUP_HOOKS StringAssert.Contains ( - "DOTNET_STARTUP_HOOKS=StartupHook", + "DOTNET_STARTUP_HOOKS=MyStartupHook", logcatOutput, - "DOTNET_STARTUP_HOOKS should be set to StartupHook" + "DOTNET_STARTUP_HOOKS should be set to MyStartupHook" ); // Verify the startup hook was called From 81b1f29c812b60334c24f7535d67e2fbae5d5b42 Mon Sep 17 00:00:00 2001 From: Jonathan Peppers Date: Wed, 21 Jan 2026 08:36:52 -0600 Subject: [PATCH 09/10] Add test for DOTNET_STARTUP_HOOKS environment variable Introduces a new test to verify that the DOTNET_STARTUP_HOOKS environment variable is set to 'StartupHook'. Also renames an existing test method for clarity. --- .../Mono.Android-Tests/System/StartupHookTest.cs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/tests/Mono.Android-Tests/Mono.Android-Tests/System/StartupHookTest.cs b/tests/Mono.Android-Tests/Mono.Android-Tests/System/StartupHookTest.cs index a2e2602b853..02dc861eb82 100644 --- a/tests/Mono.Android-Tests/Mono.Android-Tests/System/StartupHookTest.cs +++ b/tests/Mono.Android-Tests/Mono.Android-Tests/System/StartupHookTest.cs @@ -8,12 +8,19 @@ namespace SystemTests public class StartupHookTest { [Test] - public void StartupHookSupportFeatureFlagIsEnabled () + public void FeatureFlagIsEnabled () { // NOTE: this is set to true in tests\Mono.Android-Tests\Mono.Android-Tests\Mono.Android.NET-Tests.csproj Assert.IsTrue (Microsoft.Android.Runtime.RuntimeFeature.StartupHookSupport, "RuntimeFeature.StartupHookSupport should be true"); } + [Test] + public void EnvironmentVariableIsSet () + { + var value = Environment.GetEnvironmentVariable ("DOTNET_STARTUP_HOOKS"); + Assert.AreEqual ("StartupHook", value, "DOTNET_STARTUP_HOOKS should be set to 'StartupHook'"); + } + [Test] public void IsInitialized () { From 1bf0c48dd5c939fde6b81bd240a41a5f5c4f6595 Mon Sep 17 00:00:00 2001 From: Jonathan Peppers Date: Wed, 21 Jan 2026 08:48:17 -0600 Subject: [PATCH 10/10] Update Mono.Android.NET-Tests.csproj --- .../Mono.Android-Tests/Mono.Android.NET-Tests.csproj | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/Mono.Android-Tests/Mono.Android-Tests/Mono.Android.NET-Tests.csproj b/tests/Mono.Android-Tests/Mono.Android-Tests/Mono.Android.NET-Tests.csproj index d27f13ad188..eb93a305fa7 100644 --- a/tests/Mono.Android-Tests/Mono.Android-Tests/Mono.Android.NET-Tests.csproj +++ b/tests/Mono.Android-Tests/Mono.Android-Tests/Mono.Android.NET-Tests.csproj @@ -232,7 +232,8 @@ - + +