Skip to content

Commit

Permalink
Add unloadable AssemblyLoadContext API and tests (dotnet/corefx#32002)
Browse files Browse the repository at this point in the history
* Add unloadable AssemblyLoadContext API and tests

The change is based on dotnet/corefx#14763, but I had to change many things due to
the fact that the project.json files are not used anymore and due to the
slighly different semantics of the Unloading event, which now fires when
the unloading is about to start and doesn't indicate the unload is
almost done as before.

Additional changes:
* Tests for all remaining unsupported features:
  * delegate marshalling for types in collectible assemblies
  * FixedAddressValueTypeAttribute
  * COM interop
* Removed checked in binary System.Runtime.Loader.Test.Assembly.dll,
modified the msbuild projects to build it at the build time instead.
* Added the new APIs to ApiCompatBaseline


Commit migrated from dotnet/corefx@cfb501e
  • Loading branch information
janvorli authored Aug 29, 2018
1 parent 6e9321d commit 481996e
Show file tree
Hide file tree
Showing 19 changed files with 724 additions and 12 deletions.
4 changes: 2 additions & 2 deletions src/libraries/System.Runtime.Loader/Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="..\Directory.Build.props" />
<PropertyGroup>
<AssemblyVersion>4.0.3.0</AssemblyVersion>
<AssemblyVersion>4.1.0.0</AssemblyVersion>
<AssemblyKey>MSFT</AssemblyKey>
<IsNETCoreApp>true</IsNETCoreApp>
</PropertyGroup>
</Project>
</Project>
20 changes: 20 additions & 0 deletions src/libraries/System.Runtime.Loader/System.Runtime.Loader.sln
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,16 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Runtime.Loader.RefEm
{485A65F0-51C9-4B95-A7A8-A4860C231E67} = {485A65F0-51C9-4B95-A7A8-A4860C231E67}
EndProjectSection
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Runtime.Loader.Test.Assembly2", "tests\System.Runtime.Loader.Test.Assembly2\System.Runtime.Loader.Test.Assembly2.csproj", "{FBF73A8E-7889-4C7D-AFC3-509B821D0FC6}"
ProjectSection(ProjectDependencies) = postProject
{485A65F0-51C9-4B95-A7A8-A4860C231E67} = {485A65F0-51C9-4B95-A7A8-A4860C231E67}
EndProjectSection
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Runtime.Loader.Test.AssemblyNotSupported", "tests\System.Runtime.Loader.Test.AssemblyNotSupported\System.Runtime.Loader.Test.AssemblyNotSupported.csproj", "{F430F54A-7F28-4707-8006-F628B576664E}"
ProjectSection(ProjectDependencies) = postProject
{485A65F0-51C9-4B95-A7A8-A4860C231E67} = {485A65F0-51C9-4B95-A7A8-A4860C231E67}
EndProjectSection
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Runtime.Loader.Noop.Assembly", "tests\System.Runtime.Loader.Noop.Assembly\System.Runtime.Loader.Noop.Assembly.csproj", "{396D6EBF-60BD-4DAF-8783-FB403E070A57}"
ProjectSection(ProjectDependencies) = postProject
{485A65F0-51C9-4B95-A7A8-A4860C231E67} = {485A65F0-51C9-4B95-A7A8-A4860C231E67}
Expand Down Expand Up @@ -74,6 +84,14 @@ Global
{FB507A82-ACDD-4809-A030-6F9372A71194}.Debug|Any CPU.Build.0 = netcoreapp-Debug|Any CPU
{FB507A82-ACDD-4809-A030-6F9372A71194}.Release|Any CPU.ActiveCfg = netcoreapp-Release|Any CPU
{FB507A82-ACDD-4809-A030-6F9372A71194}.Release|Any CPU.Build.0 = netcoreapp-Release|Any CPU
{FBF73A8E-7889-4C7D-AFC3-509B821D0FC6}.Debug|Any CPU.ActiveCfg = netcoreapp-Debug|Any CPU
{FBF73A8E-7889-4C7D-AFC3-509B821D0FC6}.Debug|Any CPU.Build.0 = netcoreapp-Debug|Any CPU
{FBF73A8E-7889-4C7D-AFC3-509B821D0FC6}.Release|Any CPU.ActiveCfg = netcoreapp-Release|Any CPU
{FBF73A8E-7889-4C7D-AFC3-509B821D0FC6}.Release|Any CPU.Build.0 = netcoreapp-Release|Any CPU
{F430F54A-7F28-4707-8006-F628B576664E}.Debug|Any CPU.ActiveCfg = netcoreapp-Debug|Any CPU
{F430F54A-7F28-4707-8006-F628B576664E}.Debug|Any CPU.Build.0 = netcoreapp-Debug|Any CPU
{F430F54A-7F28-4707-8006-F628B576664E}.Release|Any CPU.ActiveCfg = netcoreapp-Release|Any CPU
{F430F54A-7F28-4707-8006-F628B576664E}.Release|Any CPU.Build.0 = netcoreapp-Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand All @@ -84,6 +102,8 @@ Global
{701CB3BC-00DC-435D-BDE4-C5FC29A708A9} = {1A2F9F4A-A032-433E-B914-ADD5992BB178}
{396D6EBF-60BD-4DAF-8783-FB403E070A57} = {1A2F9F4A-A032-433E-B914-ADD5992BB178}
{E3C33774-AA3D-4CED-A7A6-BDF9A7F100DF} = {1A2F9F4A-A032-433E-B914-ADD5992BB178}
{FBF73A8E-7889-4C7D-AFC3-509B821D0FC6} = {1A2F9F4A-A032-433E-B914-ADD5992BB178}
{F430F54A-7F28-4707-8006-F628B576664E} = {1A2F9F4A-A032-433E-B914-ADD5992BB178}
{485A65F0-51C9-4B95-A7A8-A4860C231E67} = {E107E9C1-E893-4E87-987E-04EF0DCEAEFD}
{FB507A82-ACDD-4809-A030-6F9372A71194} = {2E666815-2EDB-464B-9DF6-380BF4789AD4}
EndGlobalSection
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@ namespace System.Runtime.Loader
public abstract partial class AssemblyLoadContext
{
protected AssemblyLoadContext() { }
protected AssemblyLoadContext(bool isCollectible) { }
public bool IsCollectible { get { throw null; } }
public void Unload() { throw null; }
public static System.Runtime.Loader.AssemblyLoadContext Default { get { throw null; } }
public static System.Reflection.AssemblyName GetAssemblyName(string assemblyPath) { throw null; }
public static System.Runtime.Loader.AssemblyLoadContext GetLoadContext(System.Reflection.Assembly assembly) { throw null; }
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
Compat issues with assembly System.Runtime.Loader:
TypesMustExist : Type 'System.Reflection.Metadata.AssemblyExtensions' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'System.Runtime.Loader.AssemblyLoadContext..ctor(System.Boolean)' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'System.Runtime.Loader.AssemblyLoadContext.add_Resolving(System.Func<System.Runtime.Loader.AssemblyLoadContext, System.Reflection.AssemblyName, System.Reflection.Assembly>)' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'System.Runtime.Loader.AssemblyLoadContext.add_Unloading(System.Action<System.Runtime.Loader.AssemblyLoadContext>)' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'System.Runtime.Loader.AssemblyLoadContext.Default.get()' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'System.Runtime.Loader.AssemblyLoadContext.GetAssemblyName(System.String)' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'System.Runtime.Loader.AssemblyLoadContext.GetLoadContext(System.Reflection.Assembly)' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'System.Runtime.Loader.AssemblyLoadContext.IsCollectible.get()' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'System.Runtime.Loader.AssemblyLoadContext.Load(System.Reflection.AssemblyName)' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'System.Runtime.Loader.AssemblyLoadContext.LoadFromAssemblyName(System.Reflection.AssemblyName)' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'System.Runtime.Loader.AssemblyLoadContext.LoadFromAssemblyPath(System.String)' does not exist in the implementation but it does exist in the contract.
Expand All @@ -17,4 +19,5 @@ MembersMustExist : Member 'System.Runtime.Loader.AssemblyLoadContext.remove_Reso
MembersMustExist : Member 'System.Runtime.Loader.AssemblyLoadContext.remove_Unloading(System.Action<System.Runtime.Loader.AssemblyLoadContext>)' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'System.Runtime.Loader.AssemblyLoadContext.SetProfileOptimizationRoot(System.String)' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'System.Runtime.Loader.AssemblyLoadContext.StartProfileOptimization(System.String)' does not exist in the implementation but it does exist in the contract.
Total Issues: 18
MembersMustExist : Member 'System.Runtime.Loader.AssemblyLoadContext.Unload()' does not exist in the implementation but it does exist in the contract.
Total Issues: 21
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
Compat issues with assembly System.Runtime.Loader:
TypesMustExist : Type 'System.Reflection.Metadata.AssemblyExtensions' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'System.Runtime.Loader.AssemblyLoadContext..ctor(System.Boolean)' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'System.Runtime.Loader.AssemblyLoadContext.add_Resolving(System.Func<System.Runtime.Loader.AssemblyLoadContext, System.Reflection.AssemblyName, System.Reflection.Assembly>)' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'System.Runtime.Loader.AssemblyLoadContext.add_Unloading(System.Action<System.Runtime.Loader.AssemblyLoadContext>)' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'System.Runtime.Loader.AssemblyLoadContext.Default.get()' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'System.Runtime.Loader.AssemblyLoadContext.GetAssemblyName(System.String)' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'System.Runtime.Loader.AssemblyLoadContext.GetLoadContext(System.Reflection.Assembly)' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'System.Runtime.Loader.AssemblyLoadContext.IsCollectible.get()' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'System.Runtime.Loader.AssemblyLoadContext.Load(System.Reflection.AssemblyName)' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'System.Runtime.Loader.AssemblyLoadContext.LoadFromAssemblyName(System.Reflection.AssemblyName)' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'System.Runtime.Loader.AssemblyLoadContext.LoadFromAssemblyPath(System.String)' does not exist in the implementation but it does exist in the contract.
Expand All @@ -17,4 +19,5 @@ MembersMustExist : Member 'System.Runtime.Loader.AssemblyLoadContext.remove_Reso
MembersMustExist : Member 'System.Runtime.Loader.AssemblyLoadContext.remove_Unloading(System.Action<System.Runtime.Loader.AssemblyLoadContext>)' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'System.Runtime.Loader.AssemblyLoadContext.SetProfileOptimizationRoot(System.String)' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'System.Runtime.Loader.AssemblyLoadContext.StartProfileOptimization(System.String)' does not exist in the implementation but it does exist in the contract.
Total Issues: 18
MembersMustExist : Member 'System.Runtime.Loader.AssemblyLoadContext.Unload()' does not exist in the implementation but it does exist in the contract.
Total Issues: 21
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,11 @@
namespace System.Runtime.Loader.Tests
{
[SkipOnTargetFramework(TargetFrameworkMonikers.UapAot, "AssemblyLoadContext not supported on .Net Native")]
public class AssemblyLoadContextTest
public partial class AssemblyLoadContextTest
{
private const string TestAssembly = "System.Runtime.Loader.Test.Assembly";
private const string TestAssembly2 = "System.Runtime.Loader.Test.Assembly2";
private const string TestAssemblyNotSupported = "System.Runtime.Loader.Test.AssemblyNotSupported";

[Fact]
public static void GetAssemblyNameTest_ValidAssembly()
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using Xunit;
using System.Threading;

namespace System.Runtime.Loader.Tests
{

public partial class AssemblyLoadContextTest
{
class DelegateMarshallingTest : TestBase
{
[MethodImpl(MethodImplOptions.NoInlining)]
public void Execute()
{
// Delegate marshaling for types within collectible assemblies is not supported.
Assert.Throws<NotSupportedException>(() =>
{
MethodInfo methodReference = _testClassTypes[0].GetMethod("TestDelegateMarshalling");
Assert.NotNull(methodReference);
methodReference.Invoke(null, BindingFlags.DoNotWrapExceptions, Type.DefaultBinder, null, null);
});
}
}

[Fact]
public static void Unsupported_DelegateMarshalling()
{
var test = new DelegateMarshallingTest();
test.CreateContextAndLoadAssembly();
test.Execute();
test.UnloadAndClearContext();
test.CheckContextUnloaded();
}


class COMInteropTest : TestBase
{
[MethodImpl(MethodImplOptions.NoInlining)]
public void Execute()
{
// COM Interop is not supported for collectible types.
Assert.Throws<NotSupportedException>(() =>
{
Type contextMenuType = _testClassTypes[0].GetNestedType("COMClass");
Assert.NotNull(contextMenuType);
Assert.True(contextMenuType.IsCOMObject);
object contextMenu = Activator.CreateInstance(contextMenuType);
Assert.NotNull(contextMenu);
});
}
}

[Fact]
public static void Unsupported_COMInterop()
{
var test = new COMInteropTest();
test.CreateContextAndLoadAssembly();
test.Execute();
test.UnloadAndClearContext();
test.CheckContextUnloaded();
}

}
}
Loading

0 comments on commit 481996e

Please sign in to comment.