Summary
dotnet test fails for any .NET for Android test project starting with .NET SDK 11.0.100-preview.7.26376.106. The ResolveFrameworkReferences task crashes with a duplicate Microsoft.NETCore.App key.
This is an SDK-side bug, not a .NET for Android bug — see the "Not our bug" section below for proof. This issue exists to track re-enabling the test we had to disable.
Steps to Reproduce
- Install .NET SDK
11.0.100-preview.7.26376.106 (or newer) and the android workload.
- Attach an Android device or emulator.
- Run:
dotnet new androidtest -n ReproAndroidTest
cd ReproAndroidTest
dotnet build
dotnet test
You need a NuGet.config with the dotnet11 / dotnet11-transport dnceng public feeds to restore the preview Microsoft.NETCore.App.Runtime.android-* packs.
Expected Behavior
dotnet test deploys the app and runs the tests on the device.
Actual Behavior
dotnet test exits with code 1 and prints only a generic message:
Running the ComputeRunArguments target to discover run commands failed for this project. Fix the errors and warnings and run again.
The real error is visible only in a binlog:
Microsoft.NET.Sdk.FrameworkReferenceResolution.targets(411,5): error MSB4018: The "ResolveFrameworkReferences" task failed unexpectedly.
System.ArgumentException: An item with the same key has already been added. Key: Microsoft.NETCore.App
at System.Collections.Generic.Dictionary`2.Add(TKey key, TValue value)
at System.Linq.Enumerable.SpanToDictionary[TSource,TKey](ReadOnlySpan`1 source, Func`2 keySelector, IEqualityComparer`1 comparer)
at System.Linq.Enumerable.ToDictionary[TSource,TKey](IEnumerable`1 source, Func`2 keySelector, IEqualityComparer`1 comparer)
at Microsoft.NET.Build.Tasks.ResolveFrameworkReferences.ExecuteCore()
Note that dotnet test writes two binlogs; the error only appears in the second one (*-dotnet-test.binlog).
Analysis
ResolveFrameworkReferences.ExecuteCore() does:
var resolvedRuntimePacks = ResolvedRuntimePacks.ToDictionary (rp => rp.GetMetadata (MetadataKeys.FrameworkName), StringComparer.OrdinalIgnoreCase);
This throws when @(ResolvedRuntimePack) contains two items whose FrameworkName is Microsoft.NETCore.App.
The .NET SDK now makes dotnet test device-aware. SolutionAndProjectUtility selects a device (running the ComputeAvailableDevices target) and then deploys and computes run arguments:
if (project.Targets.ContainsKey (Constants.DeployToDevice) &&
!project.Build ([Constants.DeployToDevice], loggers)) {
throw new GracefulException (CliCommandStrings.RunCommandDeployFailed);
}
if (!project.Build (s_computeRunArgumentsTarget, loggers)) {
throw new GracefulException (CliCommandStrings.RunCommandEvaluationExceptionBuildFailed, s_computeRunArgumentsTarget [0]);
}
These are multiple ProjectInstance.Build () calls against the same ProjectInstance. The binlog shows ProcessFrameworkReferences executing twice, and because MSBuild task <Output ItemName="..." /> appends, the second execution adds a second Microsoft.NETCore.App runtime pack. ResolveFrameworkReferences then throws.
dotnet run does not hit this, which is what makes the failure look Android-specific when it is not.
Not our bug
Reproduced locally against a stock SDK and a released workload, with no .NET for Android PR content anywhere in the picture:
- SDK
11.0.100-preview.7.26376.106 (side-loaded, official build)
Microsoft.Android.Sdk.Windows 37.0.0-preview.6.59 (released)
| Command |
Result |
dotnet test |
exit 1 — fails |
dotnet test -p:RuntimeIdentifier=android-arm64 |
exit 1 — still fails |
dotnet run |
exit 0 — deploys and runs on device |
Two conclusions:
- Pinning a single RID does not help, so this is not caused by Android projects being multi-RID (
android-arm64;android-x64). It is caused by the target running twice.
dotnet run works on the identical project, confirming the problem is specific to the dotnet test code path.
There is no workaround available from the project or from our targets.
Impact on this repo
Xamarin.Android.Build.Tests.InstallAndRunTests.DotNetNewAndroidTest fails for the "test" cases. First seen in the dependency bump #12249, e.g. this build.
The "test" cases are disabled with Assert.Ignore referencing this issue. The "run" case still passes and remains enabled.
Action items
Summary
dotnet testfails for any .NET for Android test project starting with .NET SDK11.0.100-preview.7.26376.106. TheResolveFrameworkReferencestask crashes with a duplicateMicrosoft.NETCore.Appkey.This is an SDK-side bug, not a .NET for Android bug — see the "Not our bug" section below for proof. This issue exists to track re-enabling the test we had to disable.
Steps to Reproduce
11.0.100-preview.7.26376.106(or newer) and theandroidworkload.You need a
NuGet.configwith thedotnet11/dotnet11-transportdnceng public feeds to restore the previewMicrosoft.NETCore.App.Runtime.android-*packs.Expected Behavior
dotnet testdeploys the app and runs the tests on the device.Actual Behavior
dotnet testexits with code 1 and prints only a generic message:The real error is visible only in a binlog:
Note that
dotnet testwrites two binlogs; the error only appears in the second one (*-dotnet-test.binlog).Analysis
ResolveFrameworkReferences.ExecuteCore()does:This throws when
@(ResolvedRuntimePack)contains two items whoseFrameworkNameisMicrosoft.NETCore.App.The .NET SDK now makes
dotnet testdevice-aware.SolutionAndProjectUtilityselects a device (running theComputeAvailableDevicestarget) and then deploys and computes run arguments:These are multiple
ProjectInstance.Build ()calls against the sameProjectInstance. The binlog showsProcessFrameworkReferencesexecuting twice, and because MSBuild task<Output ItemName="..." />appends, the second execution adds a secondMicrosoft.NETCore.Appruntime pack.ResolveFrameworkReferencesthen throws.dotnet rundoes not hit this, which is what makes the failure look Android-specific when it is not.Not our bug
Reproduced locally against a stock SDK and a released workload, with no .NET for Android PR content anywhere in the picture:
11.0.100-preview.7.26376.106(side-loaded, official build)Microsoft.Android.Sdk.Windows37.0.0-preview.6.59(released)dotnet testdotnet test -p:RuntimeIdentifier=android-arm64dotnet runTwo conclusions:
android-arm64;android-x64). It is caused by the target running twice.dotnet runworks on the identical project, confirming the problem is specific to thedotnet testcode path.There is no workaround available from the project or from our targets.
Impact on this repo
Xamarin.Android.Build.Tests.InstallAndRunTests.DotNetNewAndroidTestfails for the"test"cases. First seen in the dependency bump #12249, e.g. this build.The
"test"cases are disabled withAssert.Ignorereferencing this issue. The"run"case still passes and remains enabled.Action items
ProjectInstanceperBuild ()call, or issue a singleBuild ()covering all required targets).Assert.IgnorefromDotNetNewAndroidTestand re-enable the"test"cases.dotnet build -t:Installstep in that test can also be removed, sincedotnet testrunsDeployToDeviceitself.