Skip to content

Conversation

@ericstj
Copy link
Member

@ericstj ericstj commented Feb 27, 2021

Fixes #37108

This brings back the separate assembly and package for DI.Specification.Tests.

I've removed all the ActiveIssue attributes in order to get new data from CI to see if these are all still failing on mono or not. If so I will see see about adding attributes to the derived tests classes in DI.External.Tests.

We need #48385 to complete the packaging side of this.

@ghost
Copy link

ghost commented Feb 27, 2021

Tagging subscribers to this area: @eerhardt, @maryamariyan
See info in area-owners.md if you want to be subscribed.

Issue Details

Fixes #37108

This brings back the separate assembly and package for DI.Specification.Tests.

I've removed all the ActiveIssue attributes in order to get new data from CI to see if these are all still failing on mono or not. If so I will see see about adding attributes to the derived tests classes in DI.External.Tests.

We need #48385 to complete the packaging side of this.

Author: ericstj
Assignees: -
Labels:

area-Extensions-DependencyInjection

Milestone: -

@ericstj
Copy link
Member Author

ericstj commented Feb 27, 2021

Looks like I had a merge issue when rebasing. Will fix.

@ericstj
Copy link
Member Author

ericstj commented Feb 27, 2021

Yep, this change came in which adds an assembly dependency to a test assembly to this: 21ff47c

We will need to decide how to handle that if we still want to package this.

Base automatically changed from master to main March 1, 2021 09:08
<EnableDefaultItems>true</EnableDefaultItems>
<CLSCompliant>false</CLSCompliant>
<IsPackable>true</IsPackable>
<TargetsForTfmSpecificBuildOutput>$(TargetsForTfmSpecificBuildOutput);IncludeProjectReferencesInPackage</TargetsForTfmSpecificBuildOutput>
Copy link
Member

Choose a reason for hiding this comment

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

nit: Consider encapsulating the P2P as private asset functionality as a target that can be enabled via an msbuild property.

Copy link
Member Author

Choose a reason for hiding this comment

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

I thought about this, but expect that @Anipik will probably have some more generic implementation based on other package requirements (EG: packaging content from other projects in different paths). I suspect analyzers/source-generators will hit this.

Copy link
Member

Choose a reason for hiding this comment

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

I'm fine with that but let's make sure that this specific code path then gets replaced by the more generic implementation. Unsure how to best track this.

Copy link
Member Author

Choose a reason for hiding this comment

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

@Anipik did you have a general-purpose pattern in mind for CSProj's that want to include the output of other projects?

Copy link
Member

Choose a reason for hiding this comment

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

Do we really want to do include Microsoft.Extensions.DependencyInjection.Abstractions in this package?

Copy link
Member

Choose a reason for hiding this comment

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

DI.Abstractions is added as a package dependency and not inlined into the package as its ProjectReference doesn't set Pack=true.

<ItemGroup>
<ProjectReference Include="$(LibrariesProjectRoot)Microsoft.Extensions.DependencyInjection\src\Microsoft.Extensions.DependencyInjection.csproj" SkipUseReferenceAssembly="true" />
<ProjectReference Include="$(LibrariesProjectRoot)Microsoft.Extensions.DependencyInjection.Abstractions\src\Microsoft.Extensions.DependencyInjection.Abstractions.csproj" SkipUseReferenceAssembly="true" />
<ProjectReference Include="$(LibrariesProjectRoot)Microsoft.Extensions.DependencyInjection.Specification.Tests\src\Microsoft.Extensions.DependencyInjection.Specification.Tests.csproj"/>
Copy link
Member

Choose a reason for hiding this comment

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

Do the tests in Microsoft.Extensions.DependencyInjection.Specification.Tests still get executed in our CI when we P2P them?

Copy link
Member Author

Choose a reason for hiding this comment

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

They are all abstract base classes. The derived classes in other assemblies are what execute them.

@ericstj
Copy link
Member Author

ericstj commented Mar 2, 2021

Cool, so I was able to enable most of these test on mono. The only place I needed to suppress the tests were the External DI tests were failing on the mono interpreter: both desktop and WASM. This could be an interpreter bug, or could be a problem with one of the External DI implementations. I added conditions to the tests which made use of threading so that they wouldn't run on platforms where threading was absent.

I think this is ready to merge. @eerhardt can you confirm you're OK with this as implemented?

Copy link
Member

@eerhardt eerhardt left a comment

Choose a reason for hiding this comment

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

Looks good to me

@briansull
Copy link
Contributor

This checkin may have regressed a Generate CORE_ROOT task

104 / 261 (38%, 0 failed): launching: D:\workspace\_work\1\s\artifacts\bin\coreclr\windows.x64.Checked\crossgen.exe @D:\workspace\_work\1\s\artifacts\tests\coreclr\obj\windows.x64.Checked\crossgen.out\Microsoft.Extensions.DependencyInjection.Specification.Tests.dll.rsp Error: Could not load file or assembly 'System.TestStructs, Version=1.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'. The system cannot find the file specified. (0x80070002 (COR_E_FILENOTFOUND))

https://dev.azure.com/dnceng/public/_build/results?buildId=1019715&view=logs&j=232206c9-9d3e-5b9e-c32e-6a35f74015d5&t=7fe4b998-5c8d-5e17-aa6c-5161847ae8fe&l=583

@ericstj
Copy link
Member Author

ericstj commented Mar 3, 2021

BUILDTEST: Running crossgen on framework assemblies in CORE_ROOT: D:\workspace\_work\1\s\artifacts\tests\coreclr\windows.x64.Checked\Tests\Core_Root
Running "D:\workspace\_work\1\s\dotnet.cmd" "D:\workspace\_work\1\s\artifacts\tests\coreclr\windows.x64.Checked\Tests\Core_Root\R2RTest\R2RTest.dll" compile-framework -cr "D:\workspace\_work\1\s\artifacts\tests\coreclr\windows.x64.Checked\Tests\Core_Root" --output-directory "D:\workspace\_work\1\s\artifacts\tests\coreclr\obj\windows.x64.Checked\crossgen.out" --release --nocleanup --target-arch x64 -dop 4 --large-bubble --crossgen2-parallelism 1 --crossgen --nocrossgen2 --crossgen-path "D:\workspace\_work\1\s\artifacts\bin\coreclr\windows.x64.Checked\crossgen.exe"
...
Failed to crossgen the framework
BUILDTEST: Error: crossgen precompilation of framework assemblies failed

@briansull do you know where the input to this task is determined? The problem here is that it's considering this as "framework" but it is not, it's a shipping test assembly.

@briansull
Copy link
Contributor

I don't know. The task probably considers everything in the CORE_ROOT directory as a candidate for crossgen2.
@BruceForstall

@ericstj
Copy link
Member Author

ericstj commented Mar 3, 2021

I think it gets them from here:
Downloading artifact libraries_bin_windows_x64_Release from: https://dev.azure.com/dnceng//9ee6d478-d288-47f7-aacc-f6e6d082ae6d/_apis/build/builds/1019715/artifacts?artifactName=libraries_bin_windows_x64_Release&$format=zip

Which is oddly a zip inside a zip. Inside here I see the test binary in bin\runtime\net6.0-windows-Release-x64. So the fix is not to binplace there.

@ericstj
Copy link
Member Author

ericstj commented Mar 3, 2021

Here's what's applying:

<!-- binplace to directories for the target vertical -->
<BinPlaceTargetFrameworks Include="$(NetCoreAppCurrent)-$(TargetOS)"
Condition="'$(BinPlaceForTargetVertical)' == 'true'">
<NativePath>$(NetCoreAppCurrentRuntimePath)</NativePath>
<RefPath>$(NetCoreAppCurrentRefPath)</RefPath>
<RuntimePath>$(NetCoreAppCurrentRuntimePath)</RuntimePath>
</BinPlaceTargetFrameworks>

@briansull
Copy link
Contributor

@ericstj Is the exact name of the assembly that we don't want to crossgen this: System.TestStructs.dll

I see a place where we can add it to the exclude list

@briansull
Copy link
Contributor

I submitted this PR
#49064 - Added System.TestStructs.dll to the list of excluded assemblies in CORE_ROOT

@ViktorHofer
Copy link
Member

I don't know. The task probably considers everything in the CORE_ROOT directory as a candidate for crossgen2.

Why are libraries that aren't part of the shared framework being crossgend? It looks like coreclr currently relies on a "all libraries produced" representation which doesn't exist in the product. There are libraries that are part of the shared framework and then there are libraries that are part of packages.

@BruceForstall
Copy link
Contributor

Yes, anything inside the CORE_ROOT folder gets crossgen'ed. The basic idea with these tests is to run all code (including tests) from crossgen'ed / R2R assemblies.

@trylek @janvorli @davidwrighton would know about the implementation of the R2RTest driver of this "crossgen CORE_ROOT" process.

@BruceForstall
Copy link
Contributor

We should probably have at least one R2R leg in our PR testing, as well.

@trylek
Copy link
Member

trylek commented Mar 3, 2021

For "implementation of the R2RTest driver", there's not much difference compared to the previous script-based implementation - that one was also basically iterating over all assemblies in CORE_ROOT and just skipping native ones. The number of explicit exclusions still seems pretty low compared to maintaining a list of all eligible assemblies but if someone has ideas how to make it more dynamic, I can easily take a look.

For Bruce's comment about R2R leg in PR testing, I basically concur. When I was making the Crossgen2 changes, I didn't introduce a new dedicated leg because we hadn't had any Crossgen1-specific leg in PR runs before and with the COVID-related lab capacity limitations it simply didn't seem like the ideal time for adding completely new PR legs. We do run a handful of Crossgen2 tests in PR's even today but I agree that a full leg would make them more reliable w.r.t. validation of Crossgen2-specific changes.

@BruceForstall
Copy link
Contributor

Even if we have a few R2R tests in PR, the one thing we're missing is any leg that crossgen compiles the CORE_ROOT directory.

@trylek
Copy link
Member

trylek commented Mar 3, 2021

This is an interesting observation - just unconditionally crossgening CORE_ROOT would take just a few minutes and would be definitely much faster than adding a full-fledged R2R leg crossgenning all the tests; moreover that's a one-line YAML script change I can easily make .

@BruceForstall
Copy link
Contributor

We probably don't want to alter any existing leg (or maybe we should be always R2R compiling the framework, and let our ZapDisable stress legs ignore the AOT images to give us JIT-compile coverage of the libraries?), but we could think about how to add this additional coverage.

@ericstj
Copy link
Member Author

ericstj commented Mar 3, 2021

@trylek make sure we answer the question about what needs to be part of CORE_ROOT that @ViktorHofer brought up.

Now that all tests copy locally dependencies that are not part of the shared framework perhaps we don’t need to use the entire set of runtime assemblies for CORE_ROOT?

@ViktorHofer
Copy link
Member

IIRC there are very few runtime tests that need OOB APIs like System.Drawing.Common, I believe only two or so. Bit unrelated but important for the discussion of what should go into CORE_ROOT at all.

@trylek
Copy link
Member

trylek commented Mar 3, 2021

@ericstj / @ViktorHofer - looks like there are several questions here:

Why are libraries that aren't part of the shared framework being crossgend? It looks like coreclr currently relies on a "all libraries produced" representation which doesn't exist in the product. There are libraries that are part of the shared framework and then there are libraries that are part of packages.

Bit unrelated but important for the discussion of what should go into CORE_ROOT at all.

I don't really have any good answer to that beyond that's something we haven't touched semantically in the Crossgen2 work. As I described above, previous R2R logic used super-simple scripting to basically "Crossgen[1]-compile everything in CORE_ROOT and silently ignore all errors caused by hitting native DLL's'" - I agree that's hacky, unreliable and flaky to some extent and perhaps merit cleaning up.

Cleaning this up can have several forms: as Viktor pointed out, maybe the CORE_ROOT is an overused sink of garbage that was just convenient to put in one place even though it consists of logically distinct components (CoreCLR runtime, JIT, DBI / DAC components, Win32 API contract DLLs, framework assemblies, xunit.console used internally as the test harness), maybe some more.

Making its content more structured, perhaps by using subfolders (like we already do for certain components including Crossgen2), may have positive effect on its overall management including filtering as to what gets included in Helix correlation payloads which now uses one other ad hoc hardcoded list of folders and files. I think this would be a fine thing to add as a small to medium-size (2 work-weeks or so) CoreCLR infra backlog item, potentially up for grabs.

One other thing is how we identify the list of assemblies to Crossgen. Today logic of first copying the assemblies to CORE_ROOT and only then running Crossgen(1|2) on top of them is also quite hacky, unreliable and potentially non-idempotent. A cleaner way to tackle this would be to Crossgen them directly as part of copying them from artifacts/bin to CORE_ROOT. That is also a good suggestion for a one-week CoreCLR infra work item up for grabs. Two things that complicate this are a) that it's necessary to fix this in two places for the cmd | sh build scripts, and b) that the scripts have tons of "partial execution" options that need consolidating with this optimized functionality.

Even with both these cleanups in place, we still haven't answered the question of the "framework extent" present in CORE_ROOT. In fact I noticed that many devs believe that only System.Private.CoreLib is needed to run CoreCLR tests. That is obviously not the case and the set of assemblies actually needed by the tests is a great unknown that probably also happened historically by itself, so to say.

It would be a very interesting CoreCLR infra design item to think about how to make this more explicit - for instance by explicitly specifying reference assemblies on top of some well-defined minimal set in the test projects. That would let us reason much better about the needed assembly set and its propagation to CORE_ROOT. Having said that, composing CORE_ROOT in such an incremental manner would imply one more iteration over all the 10K Pri1 test build projects which is not ideal perf-wise.

In the past, IIRC @ivdiazsa and @sdmaclea worked on making the test projects more expressive in the sense of containing more property "metadata" letting the test build system dynamically decide what to do without having to stick to hard-coded lists and blindly copying around tons of unused assemblies.

Thanks

Tomas

@ericstj
Copy link
Member Author

ericstj commented Mar 3, 2021

At least what I'm looking at is not garbage, at least not the portion that this infrastructure is using. It chose to use the library folder that contains all assemblies built in the vertical vs a different folder we already produce that contains only shared framework assemblies. We're not suggesting a huge investigation here or any large investment, just consider using a different folder.

So instead of artifacts\bin\runtime\net6.0-windows-Debug-x64

<RuntimePath>$(NetCoreAppCurrentRuntimePath)</RuntimePath>

Use artifacts\bin\pkg\net6.0\runtime\windows-Debug-x64
<RuntimePath Condition="'$(IsNETCoreAppSrc)' == 'true'">$(NETCoreAppPackageRuntimePath)\..\runtime\$(TargetOS)-$(Configuration)-$(TargetArchitecture)</RuntimePath>

If you're already consuming test directories which carry the individual test assemblies then the former is redundant and latter is all that's needed. This clean-up was something @ViktorHofer already did when changing what we binplace in the libraries test shared framework, maybe this is just something that needs to be copied into the coreclr infra?

@trylek
Copy link
Member

trylek commented Mar 3, 2021

In such case we need to figure out how that maps onto CoreCLR test build. From what I recall, we start out by running the target CopyDependencyToCoreRoot which is implemented in three different places:

<Target Name="CopyDependencyToCoreRoot"

<Target Name="CopyDependencyToCoreRoot"

<Target Name="CopyDependencyToCoreRoot">

I am not completely clear on their exact interplay but that's something we would need to figure out and somehow consolidate. IIRC from my work on the CoreCLR tests last year, src/tests/Directory.Build.targets is used by the actual tests whereas src/tests/Common/Directory.Build.targets is used by the auxiliary utilities internally used by the test harness that are also located under the Common folder (hostpolicymock, CoreCLRTestLibrary, ilasm etc.). The publishdependencytargets is a Jarret's tombstone, I think it's either completely unused or at least it has a F# part that's never been used.

That's the first step and then, five hundred lines below in the build.cmd / sh script, we optionally run Crossgen2 on the pre-populated CORE_ROOT folder. I believe that today we simply have no knowing by just looking at the CoreCLR test scripts what dependencies they use. If we could somehow deduce this information from the Roslyn compilation of the tests, we could leverage it in the subsequent phase of populating CORE_ROOT even though we need to keep in mind that YAML scripts run these phases separately and in this particular case even on different machines.

@sdmaclea
Copy link
Contributor

sdmaclea commented Mar 3, 2021

For testing, crossgen on lots of assemblies is interesting. In the past a few assemblies would trigger crossgen errors. Since crossgen tool will be used on user code too, the extra coverage is nice to have.

I don't mean to change any direction in this thread, just make sure we don't lose lots of coverage accidentally.

@ghost ghost locked as resolved and limited conversation to collaborators Apr 2, 2021
@karelz karelz added this to the 6.0.0 milestone May 20, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Microsoft.Extensions.DI.Specification.Tests need to be shipped

10 participants