dotnet / sdk

Core functionality needed to create .NET Core projects, that is shared between Visual Studio and CLI
https://dot.net/core
MIT License
2.73k stars 1.07k forks source link

New winmd reference enforcement takes down unit test host #12087

Open Scottj1s opened 4 years ago

Scottj1s commented 4 years ago

If a winmd reference slips into a unit test project's deps.json file, then all unit test operations fail with: Microsoft.VisualStudio.TestPlatform.ObjectModel.TestPlatformException: Testhost process exited with error: Failed to create CoreCLR, HRESULT: 0x80070057

work around is to remove any winmd references prior to the generation of the deps.json:

but it would be nice if these references could just be ignored, or maybe issue a warning

/cc @jkoritzinsky

dsplaisted commented 4 years ago

How does a WinMD reference "slip" into a test project's deps.json file?

I'm not entirely sure what's happening, but I doubt that the NETSDK1130 error is the problem here. Perhaps the issue is that the .NET 5 runtime won't load assemblies with a winmd file in the deps.json? I think that was intentional, but we may not have considered how it would impact tests that target earlier versions of .NET Core and do reference winmds.

@jeffschwMSFT @richlander

Scottj1s commented 4 years ago

@dsplaisted I've added diagnostics to my unit test to make it clearer what workarounds were needed for the two issues I encountered: ReferencePathWithRefAssemblies bringing in transitive winmd dependencies from a winrt component project (TestComponentCSharp), creating deps.json entries that the CLR rejected (failing the unit test). ReferencePath bringing in direct winmd dependencies from a winrt component project (TestComponentCSharp), causing the NETSDK1130 build error.

In both these cases, the winrt component project itself is doing the right thing (i.e., it should not be responsible for not publishing winmd files). It's the consuming project that must work around these issues, even though that project itself takes no dependency on the cswinrt nuget. It simply targets .NET 5, and collides with the winmd restrictions.

dsplaisted commented 4 years ago

How is the transitive winmd dependency flowing in to the test project?

I do not think that either project should be responsible for working around issues in this case. When there is a reference (transitive or not) from a managed project to a managed winRT component (that produces a WinMD), the consuming project shouldn't automatically get the WinMD reference.

So it seems like there is an issue somewhere in the tooling (the .NET SDK, or NuGet, or similar) where the WinMD reference is being chosen incorrectly.

Scottj1s commented 4 years ago

I don't know the precise mechanics (i.e, the targets involved), but the transitive dependency is standard behavior for a winrt component project - most consuming projects require it, either at build time, runtime, or both.

Agree that ideally, neither project should be responsible. In this case, the references are from managed project (unit test) to native projects (C++ winrt component, WinUI nuget, etc).

dsplaisted commented 4 years ago

What's the easiest way to reproduce this in the cswinrt repo? Just run build.cmd? Are there prerequisites (ie the Windows SDK)?

Scottj1s commented 4 years ago

Yes, clone CsWinRT, and from a VS 2019 dev prompt, run build.cmd. The unittest.csproj will spew out the workaround diags, and you can edit those targets to repro both issues. Let me know if you run into any snags.

After the first build (x64|Release by default) you can 'devenv cswinrt.sln' and iterate more quickly with a filtered build (unittest.csproj only)

wli3 commented 4 years ago

but the transitive dependency is standard behavior for a winrt component project - most consuming projects require it, either at build time, runtime, or both.

So winmd reference should flow. But just not to unit test projects?

wli3 commented 4 years ago

Microsoft.VisualStudio.TestPlatform.ObjectModel.TestPlatformException: Testhost process exited with error: Failed to create CoreCLR, HRESULT: 0x80070057

Also this is a runtime error, and NETSDK1130 is a build time error. Actually NETSDK1130 is to prevent implementation behind winmd to run since the implementation is no longer in runtime. So it is NETSDK1130 failed to prevent the test to run?

Scottj1s commented 4 years ago

@wli3 it's both errors (NETSDK1130 and runtime) that the project had to work around - details above