From 3bfe696b56d42955061990d9389183d4956f49c8 Mon Sep 17 00:00:00 2001 From: Charlie Poole Date: Tue, 30 Dec 2025 10:59:05 -0800 Subject: [PATCH] Fix problems in assemlby loading --- .../DotNetHelperTests.cs | 2 +- .../nunit.engine.core/DotNetHelper.cs | 3 +- .../Drivers/NUnitNetCore31Driver.cs | 15 ++++++---- .../Internal/AssemblyHelper.cs | 10 +------ .../Internal/TestAssemblyResolver.cs | 30 ++++++++----------- 5 files changed, 26 insertions(+), 34 deletions(-) diff --git a/src/NUnitEngine/nunit.engine.core.tests/DotNetHelperTests.cs b/src/NUnitEngine/nunit.engine.core.tests/DotNetHelperTests.cs index 3b5f89b97..c3de2cbe3 100644 --- a/src/NUnitEngine/nunit.engine.core.tests/DotNetHelperTests.cs +++ b/src/NUnitEngine/nunit.engine.core.tests/DotNetHelperTests.cs @@ -63,7 +63,7 @@ public static void CanParseInputLine(string line, string name, string packageVer [TestCase("Microsoft.NETCore.App", "8.0.0", "8.0.22")] [TestCase("Microsoft.NETCore.App", "8.0.0.0", "8.0.22")] [TestCase("Microsoft.NETCore.App", "8.0.0.100", "8.0.22")] - [TestCase("Microsoft.NETCore.App", "8.0.100", "9.0.11")] + [TestCase("Microsoft.NETCore.App", "8.0.100", "8.0.22")] [TestCase("Microsoft.AspNetCore.App", "5.0.0", "8.0.22")] // Rather than 8.0.2 [TestCase("Microsoft.AspNetCore.App", "7.0.0", "8.0.22")] // Rather than 8.0.2 [TestCase("Microsoft.AspNetCore.App", "8.0.0", "8.0.22")] // Rather than 8.0.2 diff --git a/src/NUnitEngine/nunit.engine.core/DotNetHelper.cs b/src/NUnitEngine/nunit.engine.core/DotNetHelper.cs index 213392c93..571b3fc6f 100644 --- a/src/NUnitEngine/nunit.engine.core/DotNetHelper.cs +++ b/src/NUnitEngine/nunit.engine.core/DotNetHelper.cs @@ -153,7 +153,8 @@ internal static bool FindBestRuntime(Version targetVersion, IEnumerable= targetVersion) + if (candidate.Version.Major > targetVersion.Major || + candidate.Version.Major == targetVersion.Major && candidate.Version.Minor >= candidate.Version.Minor) if (bestRuntime is null || candidate.Version.Major == bestRuntime.Version.Major) bestRuntime = candidate; } diff --git a/src/NUnitEngine/nunit.engine.core/Drivers/NUnitNetCore31Driver.cs b/src/NUnitEngine/nunit.engine.core/Drivers/NUnitNetCore31Driver.cs index 5ad6b431e..70525872e 100644 --- a/src/NUnitEngine/nunit.engine.core/Drivers/NUnitNetCore31Driver.cs +++ b/src/NUnitEngine/nunit.engine.core/Drivers/NUnitNetCore31Driver.cs @@ -1,5 +1,7 @@ // Copyright (c) Charlie Poole, Rob Prouse and Contributors. MIT License - see LICENSE.txt +//#define USE_DEFAULT_ASSEMBLY_LOAD_CONTEXT + #if NETCOREAPP3_1_OR_GREATER using System; using System.Linq; @@ -66,11 +68,19 @@ public string Load(string assemblyPath, IDictionary settings) _testAssembly = AssemblyHelper.FindLoadedAssemblyByPath(assemblyPath); if (_testAssembly != null) + { _assemblyLoadContext = AssemblyLoadContext.GetLoadContext(_testAssembly); + log.Debug($" Already loaded in context {_assemblyLoadContext}"); + } else { +#if USE_DEFAULT_ASSEMBLY_LOAD_CONTEXT + _assemblyLoadContext = AssemblyLoadContext.Default; +#else _assemblyLoadContext = new AssemblyLoadContext(Path.GetFileNameWithoutExtension(assemblyPath)); +#endif _testAssembly = _assemblyLoadContext.LoadFromAssemblyPath(assemblyPath); + log.Debug($" Loaded into new context {_assemblyLoadContext}"); } _testAssemblyResolver = new TestAssemblyResolver(_assemblyLoadContext, assemblyPath); @@ -115,11 +125,6 @@ public string Load(string assemblyPath, IDictionary settings) return ExecuteMethod(LOAD_METHOD) as string; } - private Assembly _assemblyLoadContext_Resolving(AssemblyLoadContext arg1, AssemblyName arg2) - { - throw new NotImplementedException(); - } - /// /// Counts the number of test cases for the loaded test assembly /// diff --git a/src/NUnitEngine/nunit.engine.core/Internal/AssemblyHelper.cs b/src/NUnitEngine/nunit.engine.core/Internal/AssemblyHelper.cs index bdad8aed7..b402fe970 100644 --- a/src/NUnitEngine/nunit.engine.core/Internal/AssemblyHelper.cs +++ b/src/NUnitEngine/nunit.engine.core/Internal/AssemblyHelper.cs @@ -1,6 +1,7 @@ // Copyright (c) Charlie Poole, Rob Prouse and Contributors. MIT License - see LICENSE.txt using System; +using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; @@ -86,14 +87,5 @@ public static Assembly FindLoadedAssemblyByPath(string assemblyPath) !string.IsNullOrEmpty(a.Location) && StringComparer.OrdinalIgnoreCase.Equals(Path.GetFullPath(a.Location), full)); } - - public static Assembly FindLoadedAssemblyByName(AssemblyName assemblyName) - { - return AppDomain.CurrentDomain.GetAssemblies() - .FirstOrDefault(a => - !a.IsDynamic && - !string.IsNullOrEmpty(a.Location) && - a.GetName() == assemblyName); - } } } diff --git a/src/NUnitEngine/nunit.engine.core/Internal/TestAssemblyResolver.cs b/src/NUnitEngine/nunit.engine.core/Internal/TestAssemblyResolver.cs index 58216a908..a824099a2 100644 --- a/src/NUnitEngine/nunit.engine.core/Internal/TestAssemblyResolver.cs +++ b/src/NUnitEngine/nunit.engine.core/Internal/TestAssemblyResolver.cs @@ -6,6 +6,7 @@ using Microsoft.Extensions.DependencyModel.Resolution; using System; using System.Collections.Generic; +using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; @@ -52,7 +53,7 @@ private void InitializeResolutionStrategies(AssemblyLoadContext loadContext, str foreach (var reference in assemblyDef.MainModule.GetTypeReferences()) { string fn = reference.FullName; - if (fn.StartsWith("System.Windows.") || fn.StartsWith("PresentationFramework")) + if (fn.StartsWith("System.Windows.") || fn.StartsWith("PresentationFramework") || fn == "WindowsBase") tryWindowsDesktopFirst = true; if (fn.StartsWith("Microsoft.AspNetCore.")) tryAspNetCoreFirst = true; @@ -81,25 +82,18 @@ public void Dispose() _loadContext.Resolving -= OnResolving; } - //public Assembly Resolve(AssemblyLoadContext context, AssemblyName assemblyName) - //{ - // return OnResolving(context, assemblyName); - //} - private Assembly OnResolving(AssemblyLoadContext loadContext, AssemblyName assemblyName) { - if (loadContext == null) throw new ArgumentNullException("context"); - - //var runtimeResolverPath = _assemblyDependencyResolver.ResolveAssemblyToPath(assemblyName); - //if (!string.IsNullOrEmpty(runtimeResolverPath) && File.Exists(runtimeResolverPath)) - //{ - // var loadedAssembly = _loadContext.LoadFromAssemblyPath(runtimeResolverPath); - // if (loadedAssembly != null) - // { - // log.Info($"Assembly {assemblyName} ({loadedAssembly}) is loaded using the deps.json info"); - // return loadedAssembly; - // } - //} + var runtimeResolverPath = _assemblyDependencyResolver.ResolveAssemblyToPath(assemblyName); + if (!string.IsNullOrEmpty(runtimeResolverPath) && File.Exists(runtimeResolverPath)) + { + var loadedAssembly = _loadContext.LoadFromAssemblyPath(runtimeResolverPath); + if (loadedAssembly != null) + { + log.Info($"Assembly {assemblyName} ({loadedAssembly}) is loaded using the deps.json info"); + return loadedAssembly; + } + } foreach (var strategy in ResolutionStrategies) if (strategy.TryToResolve(loadContext, assemblyName, out Assembly loadedAssembly))