Skip to content
This repository was archived by the owner on Jan 23, 2023. It is now read-only.

Commit b30aafa

Browse files
committed
Add COM unloadability tests
Add two tests to test COM unloadability: * One for using native COM server from managed COM client * One for using managed COM objects from native client
1 parent 66ecc14 commit b30aafa

File tree

5 files changed

+173
-0
lines changed

5 files changed

+173
-0
lines changed

tests/src/Common/CoreCLRTestLibrary/Utilities.cs

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
using System.Reflection;
1111
using System.Runtime.CompilerServices;
1212
using System.Runtime.InteropServices;
13+
using System.Runtime.Loader;
1314
using System.Security;
1415
using System.Text;
1516
using System.Threading;
@@ -298,5 +299,64 @@ public static extern int RegGetValueW(
298299

299300
public static IntPtr HKEY_LOCAL_MACHINE => new IntPtr(unchecked((int)0x80000002));
300301
}
302+
303+
class TestAssemblyLoadContext : AssemblyLoadContext
304+
{
305+
public TestAssemblyLoadContext() : base(isCollectible: true)
306+
{
307+
308+
}
309+
310+
protected override Assembly Load(AssemblyName assemblyName)
311+
{
312+
return null;
313+
}
314+
}
315+
316+
[MethodImpl(MethodImplOptions.NoInlining)]
317+
static int ExecuteAndUnloadInternal(string assemblyPath, string[] args, Action<AssemblyLoadContext> unloadingCallback, out WeakReference alcWeakRef)
318+
{
319+
TestAssemblyLoadContext alc = new TestAssemblyLoadContext();
320+
if (unloadingCallback != null)
321+
{
322+
alc.Unloading += unloadingCallback;
323+
}
324+
alcWeakRef = new WeakReference(alc);
325+
326+
Assembly a = alc.LoadFromAssemblyPath(assemblyPath);
327+
328+
object[] argsObjArray = (a.EntryPoint.GetParameters().Length != 0) ? new object[] { args } : null;
329+
object res = a.EntryPoint.Invoke(null, argsObjArray);
330+
331+
alc.Unload();
332+
333+
return (a.EntryPoint.ReturnType == typeof(void)) ? Environment.ExitCode : Convert.ToInt32(res);
334+
}
335+
336+
public static int ExecuteAndUnload(string assemblyPath, string[] args, Action<AssemblyLoadContext> unloadingCallback = null)
337+
{
338+
WeakReference alcWeakRef;
339+
int exitCode;
340+
341+
exitCode = ExecuteAndUnloadInternal(assemblyPath, args, unloadingCallback, out alcWeakRef);
342+
343+
for (int i = 0; i < 8 && alcWeakRef.IsAlive; i++)
344+
{
345+
GC.Collect();
346+
GC.WaitForPendingFinalizers();
347+
}
348+
349+
if (alcWeakRef.IsAlive)
350+
{
351+
exitCode += 100;
352+
Console.WriteLine("Unload failed");
353+
}
354+
else
355+
{
356+
Console.WriteLine("Unload succeeded");
357+
}
358+
359+
return exitCode;
360+
}
301361
}
302362
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
3+
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
4+
<PropertyGroup>
5+
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
6+
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
7+
<AssemblyName>NETClientPrimitivesInALC</AssemblyName>
8+
<SchemaVersion>2.0</SchemaVersion>
9+
<ProjectGuid>{85C57688-DA98-4DE3-AC9B-526E4747434C}</ProjectGuid>
10+
<OutputType>Exe</OutputType>
11+
<ProjectTypeGuids>{209912F9-0DA1-4184-9CC1-8D583BAF4A28};{87799F5D-CEBD-499D-BDBA-B2C6105CD766}</ProjectTypeGuids>
12+
<ApplicationManifest>App.manifest</ApplicationManifest>
13+
14+
<!-- Blocked on ILAsm supporting embedding resources. See https://github.com/dotnet/coreclr/issues/20819 -->
15+
<IlrtTestKind>BuildOnly</IlrtTestKind>
16+
17+
<!-- Blocked on CrossGen.exe supporting embedding resources. See https://github.com/dotnet/coreclr/issues/21006 -->
18+
<CrossGenTest>false</CrossGenTest>
19+
20+
<!-- Test unsupported outside of windows -->
21+
<TestUnsupportedOutsideWindows>true</TestUnsupportedOutsideWindows>
22+
<DisableProjectBuild Condition="'$(TargetsUnix)' == 'true'">true</DisableProjectBuild>
23+
</PropertyGroup>
24+
<!-- Default configurations to help VS understand the configurations -->
25+
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
26+
</PropertyGroup>
27+
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
28+
</PropertyGroup>
29+
<ItemGroup>
30+
<Compile Include="TestInALC.cs" />
31+
</ItemGroup>
32+
<ItemGroup>
33+
<ProjectReference Include="../../../../Common/CoreCLRTestLibrary/CoreCLRTestLibrary.csproj" />
34+
<ProjectReference Include="NetClientPrimitives.csproj" />
35+
</ItemGroup>
36+
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
37+
</Project>
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
// See the LICENSE file in the project root for more information.
4+
using System;
5+
using System.IO;
6+
using System.Reflection;
7+
8+
namespace TestInALC
9+
{
10+
class Test
11+
{
12+
static int Main(string[] args)
13+
{
14+
string currentAssemblyDirectory = Path.GetDirectoryName(new Uri(Assembly.GetExecutingAssembly().CodeBase).AbsolutePath);
15+
string testAssemblyFullPath = Path.Combine(currentAssemblyDirectory, "NETClientPrimitives.exe");
16+
return TestLibrary.Utilities.ExecuteAndUnload(testAssemblyFullPath, args);
17+
}
18+
}
19+
}
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
3+
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
4+
<PropertyGroup>
5+
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
6+
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
7+
<AssemblyName>DefaultTestInALC</AssemblyName>
8+
<SchemaVersion>2.0</SchemaVersion>
9+
<ProjectGuid>{43531C46-AFE2-4254-93C6-7F17E30D750C}</ProjectGuid>
10+
<OutputType>Exe</OutputType>
11+
<ProjectTypeGuids>{786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
12+
<SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\..\..\</SolutionDir>
13+
<DefineConstants>$(DefineConstants);STATIC</DefineConstants>
14+
<!-- Test unsupported outside of windows -->
15+
<TestUnsupportedOutsideWindows>true</TestUnsupportedOutsideWindows>
16+
<DisableProjectBuild Condition="'$(TargetsUnix)' == 'true'">true</DisableProjectBuild>
17+
</PropertyGroup>
18+
<!-- Default configurations to help VS understand the configurations -->
19+
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'"></PropertyGroup>
20+
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'"></PropertyGroup>
21+
<ItemGroup>
22+
<CodeAnalysisDependentAssemblyPaths Condition=" '$(VS100COMNTOOLS)' != '' " Include="$(VS100COMNTOOLS)..\IDE\PrivateAssemblies">
23+
<Visible>False</Visible>
24+
</CodeAnalysisDependentAssemblyPaths>
25+
</ItemGroup>
26+
<ItemGroup>
27+
<Compile Include="TestInALC.cs" />
28+
</ItemGroup>
29+
<ItemGroup>
30+
<Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
31+
</ItemGroup>
32+
<ItemGroup>
33+
<ProjectReference Include="..\CMakeLists.txt" />
34+
<ProjectReference Include="DefaultTest.csproj" />
35+
</ItemGroup>
36+
<Import Project="../../../Interop.settings.targets" />
37+
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
38+
</Project>
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
// See the LICENSE file in the project root for more information.
4+
using System;
5+
using System.IO;
6+
using System.Reflection;
7+
8+
namespace TestInALC
9+
{
10+
class Test
11+
{
12+
static int Main(string[] args)
13+
{
14+
string currentAssemblyDirectory = Path.GetDirectoryName(new Uri(Assembly.GetExecutingAssembly().CodeBase).AbsolutePath);
15+
string testAssemblyFullPath = Path.Combine(currentAssemblyDirectory, "DefaultTest.exe");
16+
return TestLibrary.Utilities.ExecuteAndUnload(testAssemblyFullPath, args);
17+
}
18+
}
19+
}

0 commit comments

Comments
 (0)