Skip to content

[TrimmableTypeMap] Integration parity tests#10827

Open
simonrozsival wants to merge 3 commits intodotnet:mainfrom
simonrozsival:dev/simonrozsival/ttm-slice-integration
Open

[TrimmableTypeMap] Integration parity tests#10827
simonrozsival wants to merge 3 commits intodotnet:mainfrom
simonrozsival:dev/simonrozsival/ttm-slice-integration

Conversation

@simonrozsival
Copy link
Member

@simonrozsival simonrozsival commented Feb 18, 2026

Stacked on #10823.
Part of #10798

Scope

  • Integration test project setup
  • UserTypes fixture assembly used by parity tests
  • Side-by-side scanner parity tests against legacy behavior
  • CI wiring for integration test execution

Review guide

Two commits — review in order:

  1. Integration parity test slice — test project, UserTypes fixture, and scanner comparison tests
  2. Wire integration tests into solution and CI — .sln entries, CI yaml, InternalsVisibleTo

@simonrozsival simonrozsival added Area: NativeAOT Issues that only occur when using NativeAOT. Area: CoreCLR Issues that only occur when using CoreCLR. copilot `copilot-cli` or other AIs were used to author this trimmable-type-map labels Feb 18, 2026
@simonrozsival simonrozsival force-pushed the dev/simonrozsival/ttm-slice-integration branch from 7dafb1e to 810c7e5 Compare February 18, 2026 15:57
@simonrozsival simonrozsival changed the base branch from dev/simonrozsival/java-peer-scanner-core to main February 18, 2026 15:57
@simonrozsival simonrozsival marked this pull request as ready for review February 18, 2026 16:04
Copilot AI review requested due to automatic review settings February 18, 2026 16:04
Copy link

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

Adds an integration test slice for TrimmableTypeMap scanner parity by building a real-user-types fixture assembly and running side-by-side comparisons against the legacy Cecil-based scanner, then wires these integration tests into the solution and Windows CI.

Changes:

  • Add Microsoft.Android.Sdk.TrimmableTypeMap.IntegrationTests project with scanner parity/comparison tests (Mono.Android + user fixture).
  • Add UserTypesFixture project to produce a “real user types” assembly referencing Mono.Android/Java.Interop.
  • Wire the integration tests into Xamarin.Android.sln, add InternalsVisibleTo, and run/publish results in the Windows CI steps.

Reviewed changes

Copilot reviewed 8 out of 8 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
tests/Microsoft.Android.Sdk.TrimmableTypeMap.IntegrationTests/UserTypesFixture/UserTypesFixture.csproj New fixture project that compiles user-type edge cases and outputs DLL next to integration tests.
tests/Microsoft.Android.Sdk.TrimmableTypeMap.IntegrationTests/UserTypesFixture/UserTypes.cs User-type fixture source covering component attributes, nested types, [Export], etc.
tests/Microsoft.Android.Sdk.TrimmableTypeMap.IntegrationTests/ScannerComparisonTests.cs New parity tests comparing legacy scanner output vs new SRM-based scanner across multiple dimensions.
tests/Microsoft.Android.Sdk.TrimmableTypeMap.IntegrationTests/MockBuildEngine.cs Minimal IBuildEngine stub for TaskLoggingHelper usage in scanner tests.
tests/Microsoft.Android.Sdk.TrimmableTypeMap.IntegrationTests/Microsoft.Android.Sdk.TrimmableTypeMap.IntegrationTests.csproj New xUnit integration test project referencing TrimmableTypeMap + Build.Tasks + fixture build output.
src/Xamarin.Android.Build.Tasks/Properties/AssemblyInfo.cs Adds InternalsVisibleTo for the new integration test assembly.
build-tools/automation/yaml-templates/build-windows-steps.yaml Runs/publishes TrimmableTypeMap integration tests in Windows CI.
Xamarin.Android.sln Adds the new integration test and fixture projects to the solution.

Comment on lines +221 to +228
[Fact]
public void ExactTypeMap_MonoAndroid ()
{
var (legacy, _) = RunLegacyScanner (MonoAndroidAssemblyPath);
var (newEntries, _) = RunNewScanner (AllAssemblyPaths);
output.WriteLine ($"Legacy: {legacy.Count} entries, New: {newEntries.Count} entries");
AssertTypeMapMatch (legacy, newEntries);
}
Copy link

Copilot AI Feb 18, 2026

Choose a reason for hiding this comment

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

These integration tests repeatedly re-scan Mono.Android.dll (and often re-run the legacy scanner) in multiple [Fact]s, which can add significant CI time since the scans traverse thousands of types. Consider caching the legacy/new scan results in static Lazy fields (or using an xUnit class fixture/collection fixture) so the expensive scans run once per test class and the individual assertions reuse the results.

Copilot uses AI. Check for mistakes.
Comment on lines +1059 to +1066
var le = legacyEntries!.OrderBy (e => e.ManagedName).First ();
var ne = newEntriesForName!.OrderBy (e => e.ManagedName).First ();

if (le.ManagedName != ne.ManagedName)
managedNameMismatches.Add ($"{javaName}: legacy='{le.ManagedName}' new='{ne.ManagedName}'");

if (le.SkipInJavaToManaged != ne.SkipInJavaToManaged)
skipMismatches.Add ($"{javaName}: legacy.skip={le.SkipInJavaToManaged} new.skip={ne.SkipInJavaToManaged}");
Copy link

Copilot AI Feb 18, 2026

Choose a reason for hiding this comment

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

AssertTypeMapMatch() groups entries by JavaName but then compares only the first ManagedName within each group. This can miss alias differences where both scanners produce the same first managed type but differ in additional managed types for the same JNI name, which undermines the “ExactTypeMap” intent. Compare the full per-JavaName entry sets (including counts) rather than only the first element.

Suggested change
var le = legacyEntries!.OrderBy (e => e.ManagedName).First ();
var ne = newEntriesForName!.OrderBy (e => e.ManagedName).First ();
if (le.ManagedName != ne.ManagedName)
managedNameMismatches.Add ($"{javaName}: legacy='{le.ManagedName}' new='{ne.ManagedName}'");
if (le.SkipInJavaToManaged != ne.SkipInJavaToManaged)
skipMismatches.Add ($"{javaName}: legacy.skip={le.SkipInJavaToManaged} new.skip={ne.SkipInJavaToManaged}");
var legacySorted = legacyEntries!
.OrderBy (e => e.ManagedName)
.ThenBy (e => e.SkipInJavaToManaged)
.ToList ();
var newSorted = newEntriesForName!
.OrderBy (e => e.ManagedName)
.ThenBy (e => e.SkipInJavaToManaged)
.ToList ();
var legacyManagedList = string.Join (", ", legacySorted.Select (e => e.ManagedName));
var newManagedList = string.Join (", ", newSorted.Select (e => e.ManagedName));
if (legacyManagedList != newManagedList)
managedNameMismatches.Add ($"{javaName}: legacy='{legacyManagedList}' new='{newManagedList}'");
var legacySkipList = string.Join (", ", legacySorted.Select (e => $"{e.ManagedName}:{e.SkipInJavaToManaged}"));
var newSkipList = string.Join (", ", newSorted.Select (e => $"{e.ManagedName}:{e.SkipInJavaToManaged}"));
if (legacySkipList != newSkipList)
skipMismatches.Add ($"{javaName}: legacy.skip={legacySkipList} new.skip={newSkipList}");

Copilot uses AI. Check for mistakes.
Add IntegrationTests and UserTypesFixture projects to Xamarin.Android.sln.
Add CI step to run integration tests and publish results. Add
InternalsVisibleTo for the integration test assembly.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@simonrozsival simonrozsival force-pushed the dev/simonrozsival/ttm-slice-integration branch from 810c7e5 to d1debed Compare February 18, 2026 18:42
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Area: CoreCLR Issues that only occur when using CoreCLR. Area: NativeAOT Issues that only occur when using NativeAOT. copilot `copilot-cli` or other AIs were used to author this trimmable-type-map

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

Comments