[TrimmableTypeMap] Scanner unit tests#10813
Open
simonrozsival wants to merge 4 commits intodotnet:mainfrom
Open
[TrimmableTypeMap] Scanner unit tests#10813simonrozsival wants to merge 4 commits intodotnet:mainfrom
simonrozsival wants to merge 4 commits intodotnet:mainfrom
Conversation
e2affc3 to
3c806bb
Compare
ec29e03 to
5dc8a66
Compare
This was referenced Feb 14, 2026
5dc8a66 to
85634c7
Compare
b6895af to
cf78bbe
Compare
f25894f to
55aa377
Compare
55aa377 to
40043e8
Compare
cf78bbe to
8cd798b
Compare
fd452b2 to
1ba6f56
Compare
8cd798b to
4dc7fc6
Compare
1ba6f56 to
54d4d99
Compare
4dc7fc6 to
1520328
Compare
54d4d99 to
c3aa816
Compare
1520328 to
265b874
Compare
c3aa816 to
b52694c
Compare
265b874 to
e709c94
Compare
b52694c to
3b6b95f
Compare
jonathanpeppers
pushed a commit
that referenced
this pull request
Feb 18, 2026
Sliced from #10805. Adds the core scanner pipeline for the TrimmableTypeMap feature — the component that reads .NET assemblies and discovers all Java peer types using `System.Reflection.Metadata`. ## What this PR adds New `Microsoft.Android.Sdk.TrimmableTypeMap` project (`netstandard2.0`, ~1500 lines) with three logical layers: ### 1. Data model and metadata type providers > `Scanner/JavaPeerInfo.cs`, `Scanner/SignatureTypeProvider.cs`, `Scanner/CustomAttributeTypeProvider.cs` - **`JavaPeerInfo`** record — represents a discovered Java peer with its JNI name, marshal methods, activation constructor info, and component attributes - **`SignatureTypeProvider`** — decodes method signatures to extract parameter types (needed for marshal method and activation constructor matching) - **`CustomAttributeTypeProvider`** — decodes `[Register]`, `[Export]`, `[Activity]` etc. attribute blobs; includes a lazy enum type cache and correct nested type resolution ### 2. AssemblyIndex — per-assembly metadata indexer > `Scanner/AssemblyIndex.cs` First phase of the pipeline. Reads a single assembly and builds an index of: - `[Register]`/`[Export]` attributes on types and methods → `RegisterInfo`/`ExportInfo` records - Component attributes (`[Activity]`, `[Service]`, `[BroadcastReceiver]`, `[ContentProvider]`) with their JNI name properties - Type definition → Java peer registration mapping Designed for per-assembly parallelism — each assembly gets its own index. ### 3. JavaPeerScanner — execution logic > `Scanner/JavaPeerScanner.cs` Second phase. Consumes all `AssemblyIndex` results and produces the final `JavaPeerInfo` list: - Resolves inheritance chains across assemblies to find the nearest registered Java ancestor - Detects activation constructors (`IntPtr` + `JniHandleOwnership`) - Collects marshal methods and exported methods with JNI signatures - Merges component attribute metadata and resolves JNI names - Flags types for unconditional preservation when component attributes specify non-default JNI names Pure function: assemblies in → peer info out, no side effects. ## Review guide Three commits, one per layer — review in order: 1. **Data model and metadata type providers** — start here for the type system 2. **AssemblyIndex** — the per-assembly indexing phase 3. **JavaPeerScanner** — the cross-assembly resolution phase Scanner unit tests follow in #10813.
Add test infrastructure for the Java peer scanner: - TestFixtures project with stub Mono.Android attributes ([Register], [Activity], [Service], etc.) and test types covering MCW bindings, user types, generics, nested types, interfaces, and component types - JavaPeerScannerTests with test helpers (ScanFixtures, FindByJavaName) and foundational assertions: type discovery, DoNotGenerateAcw flags, component unconditional marking, interface/abstract/generic metadata Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Test marshal method collection, JNI signature decoding, activation constructor resolution, base type chain walking, interface resolution, compat JNI names, and component attribute metadata merging. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Cover generic base/interface type specification resolution, component- only base detection, unregistered nested type naming, deep nesting, empty namespace types, plain subclass CRC64 naming, and unregistered types with interfaces or [Export] methods. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Add TrimmableTypeMap, TrimmableTypeMap.Tests, and TestFixtures projects to Xamarin.Android.sln. Add CI step to run scanner unit tests and publish results on the Windows build pipeline. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
3b6b95f to
f1a2847
Compare
There was a problem hiding this comment.
Pull request overview
This PR adds comprehensive unit test coverage for the Java peer scanner component of the TrimmableTypeMap feature, which was introduced in #10823. The tests validate the scanner's ability to discover and analyze Java peer types from .NET assemblies using System.Reflection.Metadata.
Changes:
- Added new xUnit-based test project with ~300 lines of test code across three test files
- Created standalone TestFixtures project with stub Android attributes and ~340 lines of representative test types
- Integrated tests into Windows CI pipeline with proper test result publishing
Reviewed changes
Copilot reviewed 10 out of 10 changed files in this pull request and generated no comments.
Show a summary per file
| File | Description |
|---|---|
| tests/Microsoft.Android.Sdk.TrimmableTypeMap.Tests/Microsoft.Android.Sdk.TrimmableTypeMap.Tests.csproj | New test project using xUnit, references TrimmableTypeMap project and TestFixtures DLL |
| tests/Microsoft.Android.Sdk.TrimmableTypeMap.Tests/TestFixtures/TestFixtures.csproj | Standalone fixture assembly targeting DotNetStableTargetFramework with stub attributes and test types |
| tests/Microsoft.Android.Sdk.TrimmableTypeMap.Tests/TestFixtures/StubAttributes.cs | Stub implementations of Android attributes (Register, Activity, Service, Export, etc.) for test isolation |
| tests/Microsoft.Android.Sdk.TrimmableTypeMap.Tests/TestFixtures/TestTypes.cs | Comprehensive catalog of test types: MCW bindings, user types with components, generics, nested types, interfaces, edge cases |
| tests/Microsoft.Android.Sdk.TrimmableTypeMap.Tests/Scanner/JavaPeerScannerTests.cs | Foundational tests: peer discovery, DoNotGenerateAcw flags, component unconditional marking, type metadata |
| tests/Microsoft.Android.Sdk.TrimmableTypeMap.Tests/Scanner/JavaPeerScannerTests.Behavior.cs | Behavior tests: marshal methods, JNI signatures, activation constructors, inheritance, interface resolution, compat names |
| tests/Microsoft.Android.Sdk.TrimmableTypeMap.Tests/Scanner/JavaPeerScannerTests.EdgeCases.cs | Edge case tests: generic TypeSpecification resolution, component-only bases, unregistered nested types, deep nesting, empty namespaces |
| src/Microsoft.Android.Sdk.TrimmableTypeMap/Microsoft.Android.Sdk.TrimmableTypeMap.csproj | Added InternalsVisibleTo for test assembly access |
| build-tools/automation/yaml-templates/build-windows-steps.yaml | Added test execution and result publishing steps for new test project |
| Xamarin.Android.sln | Added three new projects to solution: TrimmableTypeMap, TrimmableTypeMap.Tests, TestFixtures |
Member
Author
|
/azp run |
|
Azure Pipelines successfully started running 1 pipeline(s). |
Member
jonathanpeppers
left a comment
There was a problem hiding this comment.
There is a test failure in the new test project:
Failed Microsoft.Android.Sdk.TrimmableTypeMap.Tests.JavaPeerScannerTests.Scan_CustomJniNameProviderAttribute_UsesNameFromAttribute [4 ms]
Error Message:
Assert.Equal() Failure: Strings differ
↓ (pos 1)
Expected: "com/example/CustomWidget"
Actual: "crc64eb3df85c64aa1af6/CustomWidget"
↑ (pos 1)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Stacked on #10823. Adds comprehensive unit test coverage for the Java peer scanner.
Part of #10798
What this PR adds
New
Microsoft.Android.Sdk.TrimmableTypeMap.Testsproject with xUnit tests:1. Test fixtures
Stub Mono.Android attributes and a representative set of test types covering MCW bindings, user types with component attributes, generics, nested types, interfaces with invokers, and edge-case types (unregistered, empty namespace, deep nesting).
2. Foundational tests
Core discovery assertions: all peers found, DoNotGenerateAcw flags, component types marked unconditional, interface/abstract/generic metadata, assembly name populated.
3. Behavior and contract tests
Marshal method collection, JNI signature decoding for all primitive types and arrays, activation constructor inheritance, base type chain resolution, compat JNI names, custom JNI name provider attributes, nested type discovery.
4. Edge-case regression tests
Generic TypeSpecification resolution, component-only base detection, unregistered nested type naming, 3-level deep nesting, empty namespace handling, plain subclass CRC64 naming, unregistered types with interfaces/exports.
Review guide
Three commits — review in order: