Skip to content

[tests] Fix CA1416 root cause in test projects instead of suppressing it#11761

Open
simonrozsival wants to merge 3 commits into
dotnet:mainfrom
simonrozsival:android-suppress-ca1416-in-tests
Open

[tests] Fix CA1416 root cause in test projects instead of suppressing it#11761
simonrozsival wants to merge 3 commits into
dotnet:mainfrom
simonrozsival:android-suppress-ca1416-in-tests

Conversation

@simonrozsival

@simonrozsival simonrozsival commented Jun 26, 2026

Copy link
Copy Markdown
Member

Summary

Our Android-targeted test projects emit a large volume of CA1416 warnings — roughly 1300 per build in the Mono.Android.NET-Tests build alone. Rather than suppress the rule, this PR fixes the root cause by declaring each affected assembly's supported platform.

Root cause

The telltale wording is "This call site is reachable on all platforms. 'X' is only supported on: 'Android' 24.0 and later." — the platform-compatibility analyzer thinks the assembly is platform-neutral, not Android-only.

Normally the .NET SDK auto-emits an assembly-level attribute that tells the analyzer the assembly only runs on Android:

[assembly: System.Runtime.Versioning.SupportedOSPlatform("android24.0")]

But these test projects set <GenerateAssemblyInfo>false</GenerateAssemblyInfo> (to avoid clashing with their hand-written Properties/AssemblyInfo.cs). In the .NET SDK, the SupportedOSPlatformAttribute is only emitted inside CoreGenerateAssemblyInfo, which is gated entirely by GenerateAssemblyInfo == true. With it disabled, the attribute is never produced, the analyzer has no Android floor, and every call to a Mono.Android API (with minimum API level 24, essentially the entire API surface is annotated android24.0) raises CA1416.

Fix

Add [assembly: SupportedOSPlatform("android24.0")] to the affected assemblies. This states the literal truth — these test apps only ever run on Android 24+ — so the analyzer stops warning, without hiding genuine portability diagnostics the way a blanket NoWarn would.

Projects changed

Only Android-targeted test projects that both set GenerateAssemblyInfo=false and call Mono.Android APIs need this:

  • Mono.Android.NET-Tests
  • TestRunner.Core
  • CodeBehind/BuildTests

Projects intentionally left alone

  • StartupHook — also sets GenerateAssemblyInfo=false, but calls no Mono.Android APIs, so it never trips CA1416.
  • MSBuildDeviceIntegration, Xamarin.Android.McwGen-Tests, Xamarin.Android.JcwGen-Tests — use the default GenerateAssemblyInfo=true, so the SDK already emits the platform attribute.

Verification

Verified against the real Mono.Android reference assembly (Microsoft.Android.Ref.37) with a minimal net*-android project mirroring the test projects' settings (GenerateAssemblyInfo=false, SupportedOSPlatformVersion=24) and the same kinds of API calls (Object.Handle, JavaSystem.IdentityHashCode, JNIEnv.GetMethodID, Activity.OnCreate, Instrumentation, Log.Error, TextView/Button, …):

Build Result
Without the attribute Reproduced the exact CA1416 warnings ("reachable on all platforms", android 24.0)
With the attribute Build succeeded — 0 warnings

Our test projects exercise Mono.Android APIs that are annotated with
[SupportedOSPlatform("android24.0")] from helper/instrumentation code
that the platform-compatibility analyzer treats as reachable on all
platforms. This produces ~1300 CA1416 warnings per build that add no
value: the tests only ever run on Android, so the platform guards the
analyzer wants are meaningless here.

Add a tests/Directory.Build.props that chains to the repository-root
Directory.Build.props and appends CA1416 to $(NoWarn) for all test
projects.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings June 26, 2026 15:50

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Adds a tests/Directory.Build.props to suppress CA1416 (platform compatibility analyzer) warnings across all projects under tests/, reducing build log noise while preserving the repository-root build settings via an explicit import chain.

Changes:

  • Add tests/Directory.Build.props that explicitly imports the repo-root Directory.Build.props (since MSBuild only auto-imports the nearest one).
  • Append CA1416 to $(NoWarn) for all test projects under tests/.
Show a summary per file
File Description
tests/Directory.Build.props Chains to repo-root Directory.Build.props and suppresses CA1416 for all projects under tests/.

Copilot's findings

  • Files reviewed: 1/1 changed files
  • Comments generated: 1

Comment thread tests/Directory.Build.props Outdated
simonrozsival and others added 2 commits June 26, 2026 18:02
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Replace the blanket NoWarn suppression with the actual fix: declare the
assembly's supported platform.

The android-targeted test projects that set <GenerateAssemblyInfo>false</GenerateAssemblyInfo>
lose the SDK-generated [assembly: SupportedOSPlatform("android24.0")]
attribute. Without it the platform-compatibility analyzer treats the
whole assembly as platform-neutral ("reachable on all platforms") and
emits CA1416 for every call to a Mono.Android API (which, with minimum
API level 24, is essentially the entire API surface).

Add [assembly: SupportedOSPlatform("android24.0")] to the affected
projects so the analyzer knows the assemblies only run on Android 24+,
silencing CA1416 without hiding genuine portability warnings:

  - Mono.Android.NET-Tests
  - TestRunner.Core
  - CodeBehind/BuildTests

StartupHook also sets GenerateAssemblyInfo=false but calls no Mono.Android
APIs, so it needs no change. MSBuildDeviceIntegration and the Mc/JcwGen
test projects use the default GenerateAssemblyInfo=true and already get
the attribute from the SDK.

Verified with the real Mono.Android reference assembly that the same API
calls produce CA1416 without the attribute and build cleanly (0 warnings)
with it.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@simonrozsival simonrozsival changed the title [tests] Suppress CA1416 warnings in test projects [tests] Fix CA1416 root cause in test projects instead of suppressing it Jun 26, 2026
Comment on lines +6 to +10
// This test assembly only ever runs on Android (minimum API level 24). Without this
// attribute the platform-compatibility analyzer treats the assembly as platform-neutral
// (because GenerateAssemblyInfo is disabled) and emits spurious CA1416 warnings for every
// call to an [SupportedOSPlatform("android24.0")] API.
[assembly: SupportedOSPlatform ("android24.0")]

@jonathanpeppers jonathanpeppers Jun 26, 2026

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Can you set the SupportedOSPlatformVersion MSBuild property instead?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

SupportedOSPlatformVersion is actually already set on this project (<SupportedOSPlatformVersion>$(AndroidMinimumDotNetApiLevel)</SupportedOSPlatformVersion>, currently 24) — but it doesn't produce the attribute here.

The .NET SDK only turns SupportedOSPlatformVersion into [assembly: SupportedOSPlatform] inside the GenerateAssemblyInfo target, which is gated on GenerateAssemblyInfo == true (Microsoft.NET.GenerateAssemblyInfo.targets). These test projects set <GenerateAssemblyInfo>false</GenerateAssemblyInfo> to avoid clashing with the hand-written Properties/AssemblyInfo.cs, so the property is inert and no attribute is emitted. The Android SDK consumes SupportedOSPlatformVersion only for typemap/runtime generation, not for the assembly attribute.

So to drive it from the property we'd have to either:

  1. stop setting GenerateAssemblyInfo=false and move everything in Properties/AssemblyInfo.cs (including [assembly: UsesPermission] in TestRunner.Core) into MSBuild, or
  2. add a small target that emits the attribute from $(SupportedOSPlatformVersion) via WriteCodeFragment.

Do you prefer one of those over the explicit [assembly: SupportedOSPlatform]? Happy to wire up (2) if you'd like to keep it property-driven.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Ok, yeah we can remove GenerateAssemblyInfo=false, I remember this problem.

We'd have to migrate attributes to the relevant MSBuild properties -- or you get duplicates.

The MSBuild properties seem better, in general.

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