Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Changes in TFM hierarchy for .NET 6 on Android/iOS/etc #2314

Open
mattleibow opened this issue May 27, 2021 · 5 comments
Open

Changes in TFM hierarchy for .NET 6 on Android/iOS/etc #2314

mattleibow opened this issue May 27, 2021 · 5 comments

Comments

@mattleibow
Copy link

mattleibow commented May 27, 2021

The Issue

I just noticed that I got exceptions when all I did was switching the TFM of my app from monoandroid to net6.0-android.

[ERROR] FATAL UNHANDLED EXCEPTION: System.ArgumentException: File not found: Microsoft.Maui.Core.DeviceTests.dll (Parameter 'assemblyFileName')
   at Guard.FileExists(String argName, String fileName) in xunit.runner.utility.netcoreapp10.dll:token 0x6000045+0x19
   at Xunit.XunitFrontController..ctor(AppDomainSupport appDomainSupport, String assemblyFileName, String configFileName, Boolean shadowCopy, String shadowCopyFolder, ISourceInformationProvider sourceInformationProvider, IMessageSink diagnosticMessageSink) in xunit.runner.utility.netcoreapp10.dll:token 0x6000139+0x4f
   at Microsoft.DotNet.XHarness.TestRunners.Xunit.XUnitTestRunner.Run(Assembly assembly, String assemblyPath) in Microsoft.DotNet.XHarness.TestRunners.Xunit.dll:token 0x6000097+0x18
   at Microsoft.DotNet.XHarness.TestRunners.Xunit.XUnitTestRunner.Run(IEnumerable`1 testAssemblies) in Microsoft.DotNet.XHarness.TestRunners.Xunit.dll:token 0x600008f+0x22a
   at Microsoft.DotNet.XHarness.TestRunners.Common.ApplicationEntryPoint.InternalRunAsync(LogWriter logger) in Microsoft.DotNet.XHarness.TestRunners.Common.dll:token 0x600001e+0x20c
   at Microsoft.DotNet.XHarness.TestRunners.Xunit.AndroidApplicationEntryPoint.RunAsync() in Microsoft.DotNet.XHarness.TestRunners.Xunit.dll:token 0x6000009+0xbe
   at Microsoft.Maui.TestUtils.TestEntryPoint.RunTestsAsync(ITestEntryPoint testEntryPoint, Bundle arguments) in Microsoft.Maui.TestUtils.DeviceTests.dll:token 0x6000047+0xe9
   at Microsoft.Maui.TestUtils.BaseTestActivity.OnCreate(Bundle savedInstanceState) in Microsoft.Maui.TestUtils.DeviceTests.dll:token 0x600001e+0xaf
   at Microsoft.Maui.TestUtils.BaseTestInstrumentation`1.<OnRunTestsAsync>d__1[[Microsoft.Maui.DeviceTests.TestActivity, Microsoft.Maui.Core.DeviceTests, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]].MoveNext() in Microsoft.Maui.TestUtils.DeviceTests.dll:token 0x6000068+0x106
   at Microsoft.Maui.TestUtils.BaseTestInstrumentation.OnStart() in Microsoft.Maui.TestUtils.DeviceTests.dll:token 0x600002b+0x78
   at System.Threading.Tasks.Task.<>c.<ThrowAsync>b__140_1(Object state) in System.Private.CoreLib.dll:token 0x6002fc7+0x0
   at System.Threading.QueueUserWorkItemCallbackDefaultContext.Execute() in System.Private.CoreLib.dll:token 0x6002c4d+0x14
   at System.Threading.ThreadPoolWorkQueue.Dispatch() in System.Private.CoreLib.dll:token 0x6002c28+0xa0
   at System.Threading.PortableThreadPool.WorkerThread.WorkerThreadStart() in System.Private.CoreLib.dll:token 0x6002d51+0x6c
   at System.Threading.Thread.StartCallback() in System.Private.CoreLib.dll:token 0x600292e+0xe

The Reason

This is a result of a new hierarchy with .NET 6.

Previously, we had

  • Android: MonoAndroid10.0 > MonoAndroid > NetStandard2.1 > NetStandard
  • .NET Core: NetCoreApp5.0 > NetCoreApp > NetStandard2.1 > NetStandard

This meant the packages that contained NetCoreApp and NetStandard could be used to have the NetCoreApp work for .NET Core and all those, and then the NetStandard could effectively be used on .NET Framework or Xamarin.

Since .NET 6 came about, the new hierarchy is this:

  • Android: NetCoreApp6.0-Android > NetCoreApp6.0 > NetCoreApp > NetStandard2.1 > NetStandard

As a result of this changed where a "Xamarin" app is now a NetCoreApp, the restore of all the xUnit packages now use the NetCoreApp .dlls, which seem to assume a .NET Core on a desktop environment.

The one example of this is that the implementation of Guard.FileExists in the xunit.runner.utility package does different things depending on the .dll. For NetCoreApp, it check for the existence of the file. In NetStandard, it just checked the path was not null. This worked with MonoAndroid because the .dll did not actually exist on disk since it came from the .apk. Now, with .NET 6, it is using the wrong .dll.

The Fix Attempts

I tried to manually swap out the dlls at compile time, but the issue is that they are named differently.

The Extra Infos

This problem will not be unique to xUnit as this is a core change in the way .NET works. This means that it will affect all packages that use the difference of NetStandard and NetCoreApp to partition functionality for desktop/mobile.

Possible Solutions

It will be possible to compile an additional library for all the new TFMs, but this might get out of hand.

Another solution is for runtime checks to see if this is Android, then don't. For example, using https://docs.microsoft.com/dotnet/api/system.operatingsystem.isandroid

Questions

Is there a way to distinguish between the restricted world of a mobile app and then all the features of the desktop? If everything is a NetCoreApp, then what is one that is not a total NetCoreApp?

@bradwilson
Copy link
Member

So, I don't think it gonna be a problem in v3, because unit test projects will now be stand-alone executables, and you'll be able to mark your unit test project as net6.0-android directly, so the linking should all work as you would expect.

That said, it's very unlikely that we'll have any runner support in the initial alpha of v3 other than .NET Framework and .NET Core, so I'm not sure whether the .NET Core console app default will actually work in this scenario. We'll have to visit this once the first alphas are available, and see what's involved in getting the "entry point" stub for Android projects to work.

@MartyIX
Copy link

MartyIX commented Nov 10, 2022

I wanted to use dotnet test -f net6.0-maccatalyst -c Debug to run xUnit tests (https://github.com/ektrah/libsodium-core) on a mac machine but I'm getting:

Run dotnet test -f net6.0-maccatalyst -c Debug
  Determining projects to restore...
  All projects are up-to-date for restore.
/Users/runner/.dotnet/packs/Microsoft.MacCatalyst.Sdk/15.4.471/tools/msbuild/iOS/Xamarin.Shared.targets(578,3): error : A bundle identifier is required. Either add an 'ApplicationId' property in the project file, or add a 'CFBundleIdentifier' entry in the project's Info.plist file. [/Users/runner/work/libsodium-core/libsodium-core/test/Sodium.Tests/Sodium.Tests.csproj]

But now I'm very confused because I don't know answers to the following questions:

  1. Is running dotnet test -f net6.0-maccatalyst -c Debug (on a mac machine) for an xUnit test project supported or not? (Is it what this issue is about?)
  2. If not, is one supposed to use https://github.com/dotnet/xharness/ instead of running dotnet test -f net6.0-maccatalyst -c Debug?

Given that you guys work on MAUI and xUnit, any answer from your side would be greatly appreciated.

@bradwilson
Copy link
Member

bradwilson commented Nov 11, 2022

@MartyIX wrote:

Is running dotnet test -f net6.0-maccatalyst -c Debug (on a mac machine) for an xUnit test project supported or not?

This is not an explicitly tested scenario. I have zero experience with MAUI and no idea what net6.0-maccatalyst is, nor how VSTest (which is what dotnet test is) interacts with our VSTest plugin for that platform.

If not, is one supposed to use https://github.com/dotnet/xharness/ instead of running dotnet test -f net6.0-maccatalyst -c Debug?

I have no context in which to give advice here.

One thing I can say for certain: we have no intention of supporting new platforms for the v2 codebase. If this is broken with v2 and not fixable without adding a new platform, then this will be a "won't fix" for v2, and re-evaluated in the context of v3.

You could in theory test this with v3 today, though we don't yet have VSTest support, because compiling a v3 test project generates an executable that can be run directly (for .NET Core, via dotnet run or dotnet exec). What you might need in that scenario is a new entry point (we auto-inject them today for .NET Framework and .NET Core, but instructions on how to provide your own are available). You can use this override to either set up the test environment before using our in-process console runner; it should also in theory be possible to just side-step our in-process console runner entirely and provide a UI-based one, though I obviously have never tried this. XHarness might be something you could integrate in v3 that way, and could be something that's provided by the community later as v3 matures and gets closer to release.

@MartyIX
Copy link

MartyIX commented Nov 11, 2022

Thank you for your reply.

Is running dotnet test -f net6.0-maccatalyst -c Debug (on a mac machine) for an xUnit test project supported or not?

This is not an explicitly tested scenario. I have zero experience with MAUI and no idea what net6.0-maccatalyst is, nor how VSTest (which is what dotnet test is) interacts with our VSTest plugin for that platform.

I see. Well, https://github.com/terrajobst/designs/blob/main/accepted/2021/net6.0-tfms/net6.0-tfms.md explains the new TFMs but I miss some details like testing. Hence my question. AFAIK, for example, net6.0-maccatalyst (net6.0-android, etc.) is used by MAUI but it's a general concept. One simply targets some source code in .NET to run on Mac Catalyst.

But now I wonder whom to ask whether dotnet test supports / should support net6.0-maccatalyst TFM (and other mentioned in the design paper). It's confusing.

@bradwilson
Copy link
Member

At the moment, the best you can expect is that we'll just treat it like net6.0, since we have no explicit support for (or knowledge of) that TFM.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants