From 462d9d25da21d4fa9558f5ab9db8f2c3d1dbd4b8 Mon Sep 17 00:00:00 2001 From: Ben Randall Date: Fri, 15 Dec 2023 12:29:16 -0500 Subject: [PATCH] Use same pattern for loading unmanaged assemblies as managed assemblies. Loading of unmanaged assemblies suffers from the same issues as loading managed assemblies in that the wrong deps.json is used by default. This updates the TestAssemblyLoadContext to use the exact same pattern for loading unmanaged assemblies as managed assemblies. 1. Use the default assembly loading logic (I'm unsure if we actually need this since, in both managed and unmanaged, the base AssemblyLoadContext logic is a no-op and it's actually the VM that has some logic for loading assemblies). 2. Use an AssemblyDependencyResolver for the test assembly. 3. Check in the same folder as the test assembly (in case the dependencies are not fully specified in deps.json). Resolves #1253 --- .../Internal/TestAssemblyLoadContext.cs | 42 ++++++++++++++++++- 1 file changed, 41 insertions(+), 1 deletion(-) diff --git a/src/NUnitEngine/nunit.engine.core/Internal/TestAssemblyLoadContext.cs b/src/NUnitEngine/nunit.engine.core/Internal/TestAssemblyLoadContext.cs index cf9ed03f9..800de29da 100644 --- a/src/NUnitEngine/nunit.engine.core/Internal/TestAssemblyLoadContext.cs +++ b/src/NUnitEngine/nunit.engine.core/Internal/TestAssemblyLoadContext.cs @@ -3,6 +3,7 @@ #if NETCOREAPP3_1_OR_GREATER using System.Reflection; +using System.Runtime.InteropServices; using System.Runtime.Loader; using System.IO; using System; @@ -56,7 +57,7 @@ protected override Assembly Load(AssemblyName name) if (loadedAssembly != null) { log.Info("Assembly {0} ({1}) is loaded using the TestAssembliesResolver", name, GetAssemblyLocationInfo(loadedAssembly)); - + return loadedAssembly; } @@ -79,6 +80,45 @@ protected override Assembly Load(AssemblyName name) return loadedAssembly; } + protected override IntPtr LoadUnmanagedDll(string name) + { + log.Debug("Loading {0} unmanaged dll", name); + + IntPtr loadedDllHandle = base.LoadUnmanagedDll(name); + if (loadedDllHandle != IntPtr.Zero) + { + log.Info("Unmanaged DLL {0} is loaded using default base.LoadUnmanagedDll()", name); + return loadedDllHandle; + } + + string runtimeResolverPath = _runtimeResolver.ResolveUnmanagedDllToPath(name); + if (string.IsNullOrEmpty(runtimeResolverPath) == false && + File.Exists(runtimeResolverPath)) + { + loadedDllHandle = LoadUnmanagedDllFromPath(runtimeResolverPath); + } + + if (loadedDllHandle != IntPtr.Zero) + { + log.Info("Unmanaged DLL {0} ({1}) is loaded using the deps.json info", name, runtimeResolverPath); + return loadedDllHandle; + } + + string unmanagedDllPath = Path.Combine(_basePath, name + ".dll"); + if (File.Exists(unmanagedDllPath)) + { + loadedDllHandle = LoadUnmanagedDllFromPath(unmanagedDllPath); + } + + if (loadedDllHandle != IntPtr.Zero) + { + log.Info("Unmanaged DLL {0} ({1}) is loaded using base path", name, unmanagedDllPath); + return loadedDllHandle; + } + + return IntPtr.Zero; + } + private static string GetAssemblyLocationInfo(Assembly assembly) { if (assembly.IsDynamic)