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

Introduce non-shipped System.Runtime.Internal assembly #61754

Closed

Conversation

jkoritzinsky
Copy link
Member

Introduce non-shipped System.Runtime.Internal assembly for internal test usage only and remove support from our test system. Any internal APIs (primarily in the hosting space) that are needed for testing that we don't want to expose publicly should be exposed via System.Runtime.Internal for our testing infrastructure to reference.

This allows us to simplify our testing infrastructure to not have to handle tests that reference only CoreLib and to not have to build CoreLib in our test build job.

Introduce non-shipped System.Runtime.Internal assembly for internal test usage only and remove <ReferenceSystemPrivateCoreLib> support from our test system. Any internal APIs (primarily in the hosting space) that are needed for testing that we don't want to expose publically should be exposed via System.Runtime.Internal for our testing infrastructure to reference.
@ghost
Copy link

ghost commented Nov 17, 2021

Tagging subscribers to this area: @dotnet/runtime-infrastructure
See info in area-owners.md if you want to be subscribed.

Issue Details

Introduce non-shipped System.Runtime.Internal assembly for internal test usage only and remove support from our test system. Any internal APIs (primarily in the hosting space) that are needed for testing that we don't want to expose publicly should be exposed via System.Runtime.Internal for our testing infrastructure to reference.

This allows us to simplify our testing infrastructure to not have to handle tests that reference only CoreLib and to not have to build CoreLib in our test build job.

Author: jkoritzinsky
Assignees: -
Labels:

area-Infrastructure

Milestone: -

@dotnet-issue-labeler
Copy link

Note regarding the new-api-needs-documentation label:

This serves as a reminder for when your PR is modifying a ref *.cs file and adding/modifying public APIs, to please make sure the API implementation in the src *.cs file is documented with triple slash comments, so the PR reviewers can sign off that change.

Copy link
Member

@AaronRobinsonMSFT AaronRobinsonMSFT left a comment

Choose a reason for hiding this comment

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

This looks good. I'd like to see some indication for how we denote the project is only for testing and never designed to be shipped. Thoughts?

src/tests/Interop/COM/Activator/Program.cs Outdated Show resolved Hide resolved
Copy link
Member

@trylek trylek left a comment

Choose a reason for hiding this comment

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

Awesome cleanup, thanks so much Jeremy!

@trylek
Copy link
Member

trylek commented Nov 17, 2021

@AaronRobinsonMSFT - I think that "never designed to be shipped" is impossible to define. The newly introduced S.R.I just adds support for stuff that tests need but the product doesn't have a reason or desire to ship [yet, potentially].

@jkoritzinsky
Copy link
Member Author

We already have validation that we don't ship files that we don't expect in the Shared Framework SDK, so we don't need to worry about it implicitly being included there. Out-of-box packaging is an explicit opt-in, but just in case I've added an explicit MSBuild error if someone tries to pack the assembly into a NuGet package on its own.

@AaronRobinsonMSFT
Copy link
Member

We already have validation that we don't ship files that we don't expect in the Shared Framework SDK, so we don't need to worry about it implicitly being included there.

This works for me. I much prefer having that.

@AaronRobinsonMSFT
Copy link
Member

I think that "never designed to be shipped" is impossible to define.

I suppose. The point though is we need "expected to ship" or "not expected to ship" or at least the concept. In this case a verification step for the SDK handles the "expected to ship" verification so that means we intentionally say "ship it" somewhere and that was my general concern. I'm happy as long as we have a validation in one direction.

@jkotas
Copy link
Member

jkotas commented Nov 17, 2021

My personal preference would be to test the internal interfaces using reflection instead of introducing the internal contracts. IIRC, I had same feedback when some of these were introduced. It also matches how we are generally testing the internal details under libraries - we not build internal contracts for those.

@AaronRobinsonMSFT
Copy link
Member

My personal preference would be to test the internal interfaces using reflection instead of introducing the internal contracts.

@jkotas I recall that. I think the biggest annoyance there is fiddling with the Reflection API. In this case, we would need to create a new instance of types and set fields. I guess this could be performed with dynamic. I will say that simple static function exports should be much easier with C# function pointers now. Can you refresh us on the reasoning again? Is there a cost we aren't considering?

@jkotas
Copy link
Member

jkotas commented Nov 17, 2021

I think the biggest annoyance there is fiddling with the Reflection API.

If you count number of lines, I think it would be less than the annoyance of introducing the internal contracts. dynamic can help, but it should not be too bad even without dynamic (create a few helper methods).

ICastable is annoying (you would have to use a bit of reflection.emit for it), but I hope that it will go away once we get the new source generator for COM.

Can you refresh us on the reasoning again?

Consistency. If one wants to test internal details - what is going to be our guideline to decide when to use reflection vs. introducing internal contracts? We use reflection everywhere, except a few places.

@jkoritzinsky
Copy link
Member Author

For me, the reason that these contracts are different than our usual internal contracts is that they are public from System.Private.CoreLib, whereas all other contracts that we test are internal. As a result, we don't need to use reflection or InternalsVisibleTo to be able to access them easily. One of the main reasons we moved to using reflection in the libraries layer for testing internal details is because we wanted to remove all InternalsVisibleTo usage in the repo (or at least as much as possible) as it is very linker-unfriendly. Since these APIs are already public, they don't need InternalsVisibleTo or reflection to be usable, so exposing them through a ref assembly is more reasonable (at least to me).

@AaronRobinsonMSFT
Copy link
Member

they are public from System.Private.CoreLib

I think that is merely because using Reflection was deemed annoying at the time. It can't be used as the singular justification because marking them public is only for testing. They can be marked internal and the product should "just work" I believe.

@jkotas
Copy link
Member

jkotas commented Nov 18, 2021

For me, the reason that these contracts are different than our usual internal contracts is that they are public from System.Private.CoreLib, whereas all other contracts that we test are internal

I am not sure what are the other internal contracts you have in mind. For example, we have number of internal methods that support debugger, they are tested via reflection, and that form the contract between the runtime and the debugger (this contract is public from CoreLib).

If you flip these methods touched in this PR to internal, I believe that the product is still going to work fine, just the tests are going to break. (ICastable is an exception that will go away.)

@jkoritzinsky
Copy link
Member Author

Does the hosting API surface (coreclr_get_delegate) support getting internal APIs? I didn't think it supported that, I thought they had to be public. If they can be internal, then I'm much more amenable to switching to using reflection for testing.

@jkotas
Copy link
Member

jkotas commented Nov 18, 2021

Does the hosting API surface (coreclr_get_delegate) support getting internal APIs? I

I think so. I have just checked - I do not see any visibility checks.

@jkoritzinsky
Copy link
Member Author

I'll go down the route of converting our tests to use reflection.

For ICastable, I've got an idea to avoid ref-emit and I'll see how people feel about it. Since ICastable will go likely go away in the .NET 7 timeframe anyway, we have some more flexibility in what we do in the interim.

jkoritzinsky added a commit to jkoritzinsky/runtime that referenced this pull request Nov 18, 2021
…posed corelib types.

Use reflection for the hosting tests as they'll be around indefinitely.

Use the ref-assembly trick for ICastable testing since ICastable testing would require Ref-emit which makes the test significantly less readable and since ICastable will be going away within the .NET 7 timeframe. Supercedes dotnet#61754
@jkoritzinsky
Copy link
Member Author

Closing in favor of #61802

@jkoritzinsky jkoritzinsky deleted the system.runtime.internal branch November 18, 2021 23:33
@ghost ghost locked as resolved and limited conversation to collaborators Dec 19, 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.

4 participants