Skip to content

[tests] Root StartupHook test assembly directly#11280

Merged
jonathanpeppers merged 1 commit intomainfrom
trimmable-typemap-startup-hook-root-assembly
May 4, 2026
Merged

[tests] Root StartupHook test assembly directly#11280
jonathanpeppers merged 1 commit intomainfrom
trimmable-typemap-startup-hook-root-assembly

Conversation

@simonrozsival
Copy link
Copy Markdown
Member

@simonrozsival simonrozsival commented May 4, 2026

Stacked on #11252 via temporary base branch pr-11252-startup-fixes-base.

Follow-up to #11252 (comment).

Replaces the dedicated StartupHookRoots.xml descriptor with a conditional TrimmerRootAssembly item for StartupHook. Once #11252 lands, this PR should be retargeted to main and should still contain only the StartupHook root simplification.

Validation:

MSBUILDDISABLENODEREUSE=1 ./dotnet-local.sh build tests/Mono.Android-Tests/Mono.Android-Tests/Mono.Android.NET-Tests.csproj -c Release -p:_AndroidTypeMapImplementation=trimmable -p:UseMonoRuntime=false -nr:false

Copilot AI review requested due to automatic review settings May 4, 2026 15:24
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR tightens and simplifies trimming roots for the on-device runtime test app (notably rooting the StartupHook test assembly directly), while also extending the trimmable typemap/runtime/test coverage and improving typemap build/packaging plumbing for CoreCLR.

Changes:

  • Simplify CoreCLRTrimmable test rooting: use TrimmerRootAssembly for StartupHook and switch test assembly roots to RootMode="Visible" under the trimmable typemap path.
  • Improve trimmable typemap runtime behavior and tests (e.g., cached simple-reference lookup; additional disposal/finalization scenarios; scanner edge cases).
  • Adjust typemap generation/emission and MSBuild targets to better support incremental builds and CoreCLR per-ABI packaging, plus fix typemap debug duplicate handling.

Reviewed changes

Copilot reviewed 26 out of 26 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
tests/Mono.Android-Tests/Mono.Android-Tests/Xamarin.Android.RuntimeTests/NUnitInstrumentation.cs Tweaks excluded test list for CoreCLRTrimmable runtime runs.
tests/Mono.Android-Tests/Mono.Android-Tests/Mono.Android.NET-Tests.csproj Updates category exclusions and replaces/adjusts trimmer roots (including StartupHook).
tests/Mono.Android-Tests/Mono.Android-Tests/Java.Interop/TrimmableTypeMapTypeManagerTests.cs Refactors/extends trimmable typemap runtime tests (incl. disposal/finalization coverage).
tests/Mono.Android-Tests/Java.Interop-Tests/Java.Interop-Tests.NET.csproj Compiles a Java.Interop GenericMarshaler helper source directly instead of referencing the external project.
tests/Microsoft.Android.Sdk.TrimmableTypeMap.Tests/TestFixtures/TestTypes.cs Adds fixture types for nested invoker edge-case coverage.
tests/Microsoft.Android.Sdk.TrimmableTypeMap.Tests/Scanner/JavaPeerScannerTests.EdgeCases.cs Adds regression test for connector nested invoker naming.
tests/Microsoft.Android.Sdk.TrimmableTypeMap.Tests/Scanner/JavaPeerScannerTests.cs Adds content-provider authorities test and minor comment cleanup.
tests/Microsoft.Android.Sdk.TrimmableTypeMap.Tests/Generator/TypeMapModelBuilderTests.cs Updates expectations around invoker associations in the model.
tests/Microsoft.Android.Sdk.TrimmableTypeMap.Tests/Generator/TypeMapAssemblyGeneratorTests.cs Expands metadata-shape tests for UCO wrappers/ctors and activation ctor referencing.
tests/Microsoft.Android.Sdk.TrimmableTypeMap.Tests/Generator/TrimmableTypeMapGeneratorTests.cs Updates cross-assembly alias merge tests to match current ownership rules.
tests/Microsoft.Android.Sdk.TrimmableTypeMap.Tests/Generator/RootTypeMapAssemblyGeneratorTests.cs Adds validation for merged vs aggregate anchoring behavior in target attributes.
tests/Microsoft.Android.Sdk.TrimmableTypeMap.Tests/Generator/FixtureTestBase.cs Removes IL-token scanning helper no longer needed by generator tests.
src/Xamarin.Android.Build.Tasks/Utilities/TypeMappingDebugNativeAssemblyGeneratorCLR.cs Fixes Java→managed debug mapping emission to use the correct duplicate template entry.
src/Xamarin.Android.Build.Tasks/Utilities/TypeMapCecilAdapter.cs Prefers Mono.Android as the template for debug duplicates when present.
src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.TypeMap.Trimmable.targets Moves typemap assembly item population into a dedicated pre-target for incremental correctness.
src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.TypeMap.Trimmable.CoreCLR.targets Refactors CoreCLR typemap-to-store addition to batch across ABIs and depend on the new prepare target.
src/Mono.Android/Microsoft.Android.Runtime/TrimmableTypeMapTypeManager.cs Adds cached/simple-reference resolution that falls back to base-type chain when needed.
src/Mono.Android/Microsoft.Android.Runtime/TrimmableTypeMap.cs Splits native registration into an explicit post-runtime-init step; adds single-run guard.
src/Mono.Android/Microsoft.Android.Runtime/ITypeMapWithAliasing.cs Clarifies interface doc comment around returned types.
src/Mono.Android/Android.Runtime/JNIEnvInit.cs Initializes typemap data earlier and registers typemap natives after JniRuntime.SetCurrent.
src/Microsoft.Android.Sdk.TrimmableTypeMap/Scanner/JavaPeerScanner.cs Normalizes connector-managed type names consistently (nested type separator handling).
src/Microsoft.Android.Sdk.TrimmableTypeMap/Scanner/AssemblyIndex.cs Captures ContentProvider authorities (including ctor array form) into component metadata.
src/Microsoft.Android.Sdk.TrimmableTypeMap/Generator/TypeMapAssemblyEmitter.cs Updates emitted UCO wrapper bodies and references internal runtime helpers for exception bridging behavior.
src/Microsoft.Android.Sdk.TrimmableTypeMap/Generator/RootTypeMapAssemblyGenerator.cs Emits target attributes differently for merged vs per-assembly universes (anchor selection).
src/Microsoft.Android.Sdk.TrimmableTypeMap/Generator/PEAssemblyBuilder.cs Increases default maxstack for emitted bodies with locals to avoid verifier issues.
src/Microsoft.Android.Sdk.TrimmableTypeMap/Generator/ModelBuilder.cs Ensures invoker types get managed→proxy associations where needed; minor string helper update.

Comment on lines +85 to +103
internal static unsafe void RegisterNativeMethods ()
{
// Use the `string` overload of `JniType` deliberately. Its underlying
// `JniEnvironment.Types.TryFindClass(string, bool)` tries raw JNI `FindClass`
// first and, if that fails, falls back to `Class.forName(name, true, info.Runtime.ClassLoader)`,
// which resolves via the runtime's app ClassLoader — the same one that loads
// `mono.android.Runtime` from the APK.
// The `ReadOnlySpan<byte>` overload (see external/Java.Interop/src/Java.Interop/Java.Interop/JniEnvironment.Types.cs)
// only calls raw JNI `FindClass`, which resolves via the system ClassLoader on
// Android and returns a different `Class` instance from the one JCWs reference.
// Registering natives on that other instance is silently wrong.
using var runtimeClass = new JniType ("mono/android/Runtime");
fixed (byte* name = "registerNatives"u8, sig = "(Ljava/lang/Class;)V"u8) {
var onRegisterNatives = (IntPtr)(delegate* unmanaged<IntPtr, IntPtr, IntPtr, void>)&OnRegisterNatives;
var method = new JniNativeMethod (name, sig, onRegisterNatives);
JniEnvironment.Types.RegisterNatives (runtimeClass.PeerReference, [method]);
lock (s_initLock) {
if (s_nativeMethodsRegistered) {
throw new InvalidOperationException ("TrimmableTypeMap native methods have already been registered.");
}

if (s_instance is null) {
throw new InvalidOperationException (
"TrimmableTypeMap has not been initialized. Ensure RuntimeFeature.TrimmableTypeMap is enabled and the JNI runtime is initialized.");
}

using var runtimeClass = new JniType ("mono/android/Runtime"u8);
fixed (byte* name = "registerNatives"u8, sig = "(Ljava/lang/Class;)V"u8) {
var onRegisterNatives = (IntPtr)(delegate* unmanaged<IntPtr, IntPtr, IntPtr, void>)&OnRegisterNatives;
var method = new JniNativeMethod (name, sig, onRegisterNatives);
JniEnvironment.Types.RegisterNatives (runtimeClass.PeerReference, [method]);
}
s_nativeMethodsRegistered = true;
@simonrozsival simonrozsival changed the base branch from main to pr-11252-startup-fixes-base May 4, 2026 15:38
@simonrozsival simonrozsival force-pushed the trimmable-typemap-startup-hook-root-assembly branch from e8a15d3 to 04969c5 Compare May 4, 2026 15:41
@simonrozsival simonrozsival changed the base branch from pr-11252-startup-fixes-base to main May 4, 2026 17:44
Replace the dedicated StartupHookRoots.xml descriptor with a conditional TrimmerRootAssembly item, matching the rest of the test project roots and avoiding a single-purpose descriptor file.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@simonrozsival simonrozsival force-pushed the trimmable-typemap-startup-hook-root-assembly branch from 5dc9e05 to f8749ea Compare May 4, 2026 18:31
@jonathanpeppers jonathanpeppers merged commit baa5bff into main May 4, 2026
3 checks passed
@jonathanpeppers jonathanpeppers deleted the trimmable-typemap-startup-hook-root-assembly branch May 4, 2026 20:49
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants