Skip to content

Commit

Permalink
Merge pull request #1337 from svg2003/issue-1330-v4
Browse files Browse the repository at this point in the history
Issue 1330 v4
  • Loading branch information
OsirisTerje committed Apr 20, 2023
2 parents b92df46 + 38d141e commit 8f472b0
Show file tree
Hide file tree
Showing 2 changed files with 101 additions and 9 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ namespace NUnit.Engine.Internal
{
internal sealed class TestAssemblyLoadContext : AssemblyLoadContext
{
private static readonly Logger log = InternalTrace.GetLogger(typeof(TestAssemblyLoadContext));

private readonly string _testAssemblyPath;
private readonly string _basePath;
private readonly TestAssemblyResolver _resolver;
Expand All @@ -27,19 +29,16 @@ public TestAssemblyLoadContext(string testAssemblyPath)

protected override Assembly Load(AssemblyName name)
{
var assemblies = AppDomain.CurrentDomain.GetAssemblies();
var loadedAssembly = assemblies.FirstOrDefault(x => x.GetName().Name == name.Name);
if (loadedAssembly != null)
{
return loadedAssembly;
}
log.Debug("Loading {0} assembly", name);

loadedAssembly = base.Load(name);
var loadedAssembly = base.Load(name);
if (loadedAssembly != null)
{
log.Info("Assembly {0} ({1}) is loaded using default base.Load()", name, GetAssemblyLocationInfo(loadedAssembly));
return loadedAssembly;
}


var runtimeResolverPath = _runtimeResolver.ResolveAssemblyToPath(name);
if (string.IsNullOrEmpty(runtimeResolverPath) == false &&
File.Exists(runtimeResolverPath))
Expand All @@ -49,12 +48,15 @@ protected override Assembly Load(AssemblyName name)

if (loadedAssembly != null)
{
log.Info("Assembly {0} ({1}) is loaded using the deps.json info", name, GetAssemblyLocationInfo(loadedAssembly));
return loadedAssembly;
}

loadedAssembly = _resolver.Resolve(this, name);
if (loadedAssembly != null)
{
log.Info("Assembly {0} ({1}) is loaded using the TestAssembliesResolver", name, GetAssemblyLocationInfo(loadedAssembly));

return loadedAssembly;
}

Expand All @@ -68,8 +70,29 @@ protected override Assembly Load(AssemblyName name)
loadedAssembly = LoadFromAssemblyPath(assemblyPath);
}

if (loadedAssembly != null)
{
log.Info("Assembly {0} ({1}) is loaded using base path", name, GetAssemblyLocationInfo(loadedAssembly));
return loadedAssembly;
}

return loadedAssembly;
}

private static string GetAssemblyLocationInfo(Assembly assembly)
{
if (assembly.IsDynamic)
{
return $"Dynamic {assembly.FullName}";
}

if (string.IsNullOrEmpty(assembly.Location))
{
return $"No location for {assembly.FullName}";
}

return $"{assembly.FullName} from {assembly.Location}";
}
}
}

Expand Down
73 changes: 71 additions & 2 deletions src/NUnitEngine/nunit.engine.core/Internal/TestAssemblyResolver.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ namespace NUnit.Engine.Internal
{
internal sealed class TestAssemblyResolver : IDisposable
{
private static readonly Logger log = InternalTrace.GetLogger(typeof(TestAssemblyResolver));

private readonly ICompilationAssemblyResolver _assemblyResolver;
private readonly DependencyContext _dependencyContext;
private readonly AssemblyLoadContext _loadContext;
Expand Down Expand Up @@ -62,6 +64,14 @@ public Assembly Resolve(AssemblyLoadContext context, AssemblyName name)

private Assembly OnResolving(AssemblyLoadContext context, AssemblyName name)
{
context = context ?? _loadContext;

if (TryLoadFromTrustedPlatformAssemblies(context, name, out var loadedAssembly))
{
log.Info("'{0}' assembly is loaded from trusted path '{1}'", name, loadedAssembly.Location);
return loadedAssembly;
}

foreach (var library in _dependencyContext.RuntimeLibraries)
{
var wrapper = new CompilationLibrary(
Expand All @@ -79,24 +89,81 @@ private Assembly OnResolving(AssemblyLoadContext context, AssemblyName name)
foreach (var assemblyPath in assemblies)
{
if (name.Name == Path.GetFileNameWithoutExtension(assemblyPath))
return _loadContext.LoadFromAssemblyPath(assemblyPath);
{
loadedAssembly = context.LoadFromAssemblyPath(assemblyPath);
log.Info("'{0}' ({1}) assembly is loaded from runtime libraries {2} dependencies",
name,
loadedAssembly.Location,
library.Name);

return loadedAssembly;
}
}
}

if (name.Version == null)
{
return null;
}

foreach (string frameworkDirectory in AdditionalFrameworkDirectories)
{
var versionDir = FindBestVersionDir(frameworkDirectory, name.Version);

if (versionDir != null)
{
string candidate = Path.Combine(frameworkDirectory, versionDir, name.Name + ".dll");
if (File.Exists(candidate))
return _loadContext.LoadFromAssemblyPath(candidate);
{
loadedAssembly = context.LoadFromAssemblyPath(candidate);
log.Info("'{0}' ({1}) assembly is loaded from AdditionalFrameworkDirectory {2} dependencies with best candidate version {3}",
name,
loadedAssembly.Location,
frameworkDirectory,
versionDir);

return loadedAssembly;
}
else
{
log.Debug("Best version dir for {0} is {1}, but there is no {2} file", frameworkDirectory, versionDir, candidate);
}
}
}

log.Info("Cannot resolve assembly '{0}'", name);
return null;
}

private static bool TryLoadFromTrustedPlatformAssemblies(AssemblyLoadContext context, AssemblyName assemblyName, out Assembly loadedAssembly)
{
// https://learn.microsoft.com/en-us/dotnet/core/dependency-loading/default-probing
loadedAssembly = null;
var trustedAssemblies = System.AppContext.GetData("TRUSTED_PLATFORM_ASSEMBLIES") as string;
if (string.IsNullOrEmpty(trustedAssemblies))
{
return false;
}

var separator = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? ";" : ":";
foreach (var assemblyPath in trustedAssemblies.Split(separator))
{
var fileName = Path.GetFileNameWithoutExtension(assemblyPath);
if (string.Equals(fileName, assemblyName.Name, StringComparison.InvariantCultureIgnoreCase) == false)
{
continue;
}

if (File.Exists(assemblyPath))
{
loadedAssembly = context.LoadFromAssemblyPath(assemblyPath);
return true;
}
}

return false;
}

private static string GetDotNetInstallDirectory()
{
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
Expand All @@ -119,9 +186,11 @@ private static string FindBestVersionDir(string libraryDir, Version targetVersio
{
Version version;
if (TryGetVersionFromString(Path.GetFileName(subdir), out version))
{
if (version >= targetVersion)
if (bestVersion.Major == 0 || bestVersion > version)
bestVersion = version;
}
}

return bestVersion.Major > 0
Expand Down

0 comments on commit 8f472b0

Please sign in to comment.