pschelpdesk/Vendor/Prise.Tests/AssemblyLoading/DefaultAssemblyLoadStrategyTests.cs
2024-11-04 20:45:34 +01:00

222 lines
14 KiB
C#

using Microsoft.VisualStudio.TestTools.UnitTesting;
using Moq;
using Prise.AssemblyLoading;
using Prise.Tests.Plugins;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.Loader;
using System.Threading.Tasks;
namespace Prise.Tests.AssemblyLoading
{
[TestClass]
public class DefaultAssemblyLoadStrategyTests : TestBase
{
[TestMethod]
public async Task Ctor_Works()
{
Assert.IsNotNull(new DefaultAssemblyLoadStrategy());
}
[TestMethod]
public async Task LoadAssembly_Returns_Null_For_Empty_AssemblyName()
{
var sut = new DefaultAssemblyLoadStrategy();
var emptyAssemblyname = new AssemblyName();
var initialPluginLoadDirectory = GetPathToAssemblies();
Assert.IsNull(sut.LoadAssembly(initialPluginLoadDirectory, emptyAssemblyname, null, null, null, null)?.Assembly);
}
[TestMethod]
public async Task LoadAssembly_Returns_Null_When_AssemblyName_NotFound()
{
var sut = new DefaultAssemblyLoadStrategy();
var assemblyname = new AssemblyName("Newtonsoft.Json.dll");
var pluginDependencyContext = this.mockRepository.Create<IPluginDependencyContext>();
var loadFromDependencyContext = CreateLookupFunction((c, a) => ValueOrProceed<AssemblyFromStrategy>.Proceed());
var loadFromRemote = CreateLookupFunction((c, a) => ValueOrProceed<AssemblyFromStrategy>.Proceed());
var loadFromAppDomain = CreateLookupFunction((c, a) => ValueOrProceed<RuntimeAssemblyShim>.Proceed());
var initialPluginLoadDirectory = GetPathToAssemblies();
pluginDependencyContext
.Setup(p => p.HostDependencies).Returns(Enumerable.Empty<HostDependency>());
pluginDependencyContext
.Setup(p => p.RemoteDependencies).Returns(Enumerable.Empty<RemoteDependency>());
Assert.IsNull(sut.LoadAssembly(initialPluginLoadDirectory, assemblyname, pluginDependencyContext.Object, loadFromDependencyContext, loadFromRemote, loadFromAppDomain)?.Assembly);
}
[TestMethod]
public async Task LoadAssembly_Returns_Null_From_AppDomain_When_IsHostAssembly_And_Not_RemoteAssembly()
{
var sut = new DefaultAssemblyLoadStrategy();
var pluginDependencyContext = this.mockRepository.Create<IPluginDependencyContext>();
var initialPluginLoadDirectory = GetPathToAssemblies();
var someAssembly = Assembly.LoadFile(Path.Combine(initialPluginLoadDirectory, "Newtonsoft.Json.dll"));
var someAssemblyName = someAssembly.GetName();
var loadFromDependencyContext = CreateLookupFunction((c, a) => ValueOrProceed<AssemblyFromStrategy>.Proceed());
var loadFromRemote = CreateLookupFunction((c, a) => ValueOrProceed<AssemblyFromStrategy>.Proceed());
var loadFromAppDomain = CreateLookupFunction((c, a) => ValueOrProceed<RuntimeAssemblyShim>.FromValue(new RuntimeAssemblyShim(someAssembly, RuntimeLoadFlag.FromRequestedVersion), false));
// Mock the fact that it was setup as a host assembly that should be loaded from the host.
pluginDependencyContext
.Setup(p => p.HostDependencies).Returns(new List<HostDependency> { new HostDependency { DependencyName = someAssemblyName } });
pluginDependencyContext
.Setup(p => p.RemoteDependencies).Returns(Enumerable.Empty<RemoteDependency>());
Assert.IsNull(sut.LoadAssembly(initialPluginLoadDirectory, someAssemblyName, pluginDependencyContext.Object, loadFromDependencyContext, loadFromRemote, loadFromAppDomain)?.Assembly);
}
[TestMethod]
public async Task LoadAssembly_Returns_NotNull_From_AppDomain_When_IsHostAssembly_And_Not_RemoteAssembly_FromRuntimeVersion()
{
var sut = new DefaultAssemblyLoadStrategy();
var pluginDependencyContext = this.mockRepository.Create<IPluginDependencyContext>();
var initialPluginLoadDirectory = GetPathToAssemblies();
var someAssembly = Assembly.LoadFile(Path.Combine(initialPluginLoadDirectory, "Newtonsoft.Json.dll"));
var someAssemblyName = someAssembly.GetName();
var loadFromDependencyContext = CreateLookupFunction((c, a) => ValueOrProceed<AssemblyFromStrategy>.Proceed());
var loadFromRemote = CreateLookupFunction((c, a) => ValueOrProceed<AssemblyFromStrategy>.Proceed());
var loadFromAppDomain = CreateLookupFunction((c, a) => ValueOrProceed<RuntimeAssemblyShim>.FromValue(new RuntimeAssemblyShim(someAssembly, RuntimeLoadFlag.FromRuntimeVersion), false));
// Mock the fact that it was setup as a host assembly that should be loaded from the host.
pluginDependencyContext
.Setup(p => p.HostDependencies).Returns(new List<HostDependency> { new HostDependency { DependencyName = someAssemblyName } });
pluginDependencyContext
.Setup(p => p.RemoteDependencies).Returns(Enumerable.Empty<RemoteDependency>());
Assert.AreEqual(someAssembly, sut.LoadAssembly(initialPluginLoadDirectory, someAssemblyName, pluginDependencyContext.Object, loadFromDependencyContext, loadFromRemote, loadFromAppDomain)?.Assembly);
}
[TestMethod]
public async Task LoadAssembly_Returns_Null_From_AppDomain_When_NOT_IsHostAssembly_And_RemoteAssembly()
{
var sut = new DefaultAssemblyLoadStrategy();
var pluginDependencyContext = this.mockRepository.Create<IPluginDependencyContext>();
var initialPluginLoadDirectory = GetPathToAssemblies();
var someAssembly = Assembly.LoadFile(Path.Combine(initialPluginLoadDirectory, "Newtonsoft.Json.dll"));
var someAssemblyName = someAssembly.GetName();
var loadFromDependencyContext = CreateLookupFunction((c, a) => ValueOrProceed<AssemblyFromStrategy>.Proceed());
var loadFromRemote = CreateLookupFunction((c, a) => ValueOrProceed<AssemblyFromStrategy>.Proceed());
var loadFromAppDomain = CreateLookupFunction((c, a) => ValueOrProceed<RuntimeAssemblyShim>.Proceed());
// Mock the fact that it was setup as a host assembly that should be loaded from the host.
pluginDependencyContext
.Setup(p => p.HostDependencies).Returns(new List<HostDependency> { new HostDependency { DependencyName = someAssemblyName } });
// Mock the fact that it was ALSO setup as a remote assembly that should be loaded from the plugin.
pluginDependencyContext
.Setup(p => p.RemoteDependencies).Returns(new List<RemoteDependency> { new RemoteDependency { DependencyName = someAssemblyName } });
Assert.IsNull(sut.LoadAssembly(initialPluginLoadDirectory, someAssemblyName, pluginDependencyContext.Object, loadFromDependencyContext, loadFromRemote, loadFromAppDomain)?.Assembly);
}
[TestMethod]
public async Task LoadAssembly_Returns_Assembly_From_DependencyContext()
{
var sut = new DefaultAssemblyLoadStrategy();
var pluginDependencyContext = this.mockRepository.Create<IPluginDependencyContext>();
var initialPluginLoadDirectory = GetPathToAssemblies();
var someAssembly = Assembly.LoadFile(Path.Combine(initialPluginLoadDirectory, "Newtonsoft.Json.dll"));
var someAssemblyName = someAssembly.GetName();
var loadFromDependencyContext = CreateLookupFunction((c, a) => ValueOrProceed<AssemblyFromStrategy>.FromValue(AssemblyFromStrategy.Releasable(someAssembly), false));
var loadFromRemote = CreateLookupFunction((c, a) => ValueOrProceed<AssemblyFromStrategy>.Proceed());
var loadFromAppDomain = CreateLookupFunction((c, a) => ValueOrProceed<RuntimeAssemblyShim>.Proceed());
pluginDependencyContext
.Setup(p => p.HostDependencies).Returns(Enumerable.Empty<HostDependency>());
pluginDependencyContext
.Setup(p => p.RemoteDependencies).Returns(Enumerable.Empty<RemoteDependency>());
Assert.AreEqual(someAssembly, sut.LoadAssembly(initialPluginLoadDirectory, someAssemblyName, pluginDependencyContext.Object, loadFromDependencyContext, loadFromRemote, loadFromAppDomain)?.Assembly);
}
[TestMethod]
public async Task LoadAssembly_Returns_Assembly_From_Remote()
{
var sut = new DefaultAssemblyLoadStrategy();
var pluginDependencyContext = this.mockRepository.Create<IPluginDependencyContext>();
var initialPluginLoadDirectory = GetPathToAssemblies();
var someAssembly = Assembly.LoadFile(Path.Combine(initialPluginLoadDirectory, "Newtonsoft.Json.dll"));
var someAssemblyName = someAssembly.GetName();
var loadFromDependencyContext = CreateLookupFunction((c, a) => ValueOrProceed<AssemblyFromStrategy>.Proceed());
var loadFromRemote = CreateLookupFunction((c, a) => ValueOrProceed<AssemblyFromStrategy>.FromValue(AssemblyFromStrategy.Releasable(someAssembly), false));
var loadFromAppDomain = CreateLookupFunction((c, a) => ValueOrProceed<RuntimeAssemblyShim>.Proceed());
pluginDependencyContext
.Setup(p => p.HostDependencies).Returns(Enumerable.Empty<HostDependency>());
pluginDependencyContext
.Setup(p => p.RemoteDependencies).Returns(Enumerable.Empty<RemoteDependency>());
Assert.AreEqual(someAssembly, sut.LoadAssembly(initialPluginLoadDirectory, someAssemblyName, pluginDependencyContext.Object, loadFromDependencyContext, loadFromRemote, loadFromAppDomain)?.Assembly);
}
[TestMethod]
public async Task LoadUnmanagedDll_Returns_AssemblyPath_FromDependencyContext()
{
var sut = new DefaultAssemblyLoadStrategy();
var pluginDependencyContext = this.mockRepository.Create<IPluginDependencyContext>();
var initialPluginLoadDirectory = GetPathToAssemblies();
var someAssembly = Assembly.LoadFile(Path.Combine(initialPluginLoadDirectory, "Newtonsoft.Json.dll"));
var someAssemblyName = someAssembly.GetName();
var loadFromDependencyContext = CreateLookupFunction<string, string>((c, a) => ValueOrProceed<string>.FromValue(someAssemblyName.Name, false));
var loadFromRemote = CreateLookupFunction<string, string>((c, a) => ValueOrProceed<string>.Proceed());
var loadFromAppDomain = CreateLookupFunction<string, IntPtr>((c, a) => ValueOrProceed<IntPtr>.FromValue(IntPtr.Zero, false));
var result = sut.LoadUnmanagedDll(initialPluginLoadDirectory, someAssemblyName.Name, pluginDependencyContext.Object, loadFromDependencyContext, loadFromRemote, loadFromAppDomain);
Assert.AreEqual(someAssemblyName.Name, result.Path);
Assert.AreEqual(IntPtr.Zero, result.Pointer);
}
[TestMethod]
public async Task LoadUnmanagedDll_Returns_AssemblyPointer_FromAppDomain()
{
var sut = new DefaultAssemblyLoadStrategy();
var pluginDependencyContext = this.mockRepository.Create<IPluginDependencyContext>();
var initialPluginLoadDirectory = GetPathToAssemblies();
var someAssembly = Assembly.LoadFile(Path.Combine(initialPluginLoadDirectory, "Newtonsoft.Json.dll"));
var someAssemblyName = someAssembly.GetName();
var loadFromDependencyContext = CreateLookupFunction<string, string>((c, a) => ValueOrProceed<string>.Proceed());
var loadFromRemote = CreateLookupFunction<string, string>((c, a) => ValueOrProceed<string>.Proceed());
var loadFromAppDomain = CreateLookupFunction<string, IntPtr>((c, a) => ValueOrProceed<IntPtr>.FromValue(new IntPtr(100), false));
var result = sut.LoadUnmanagedDll(initialPluginLoadDirectory, someAssemblyName.Name, pluginDependencyContext.Object, loadFromDependencyContext, loadFromRemote, loadFromAppDomain);
Assert.IsNull(result.Path);
Assert.AreEqual(new IntPtr(100), result.Pointer);
}
[TestMethod]
public async Task LoadUnmanagedDll_Returns_AssemblyPath_FromRemote()
{
var sut = new DefaultAssemblyLoadStrategy();
var pluginDependencyContext = this.mockRepository.Create<IPluginDependencyContext>();
var initialPluginLoadDirectory = GetPathToAssemblies();
var someAssembly = Assembly.LoadFile(Path.Combine(initialPluginLoadDirectory, "Newtonsoft.Json.dll"));
var someAssemblyName = someAssembly.GetName();
var loadFromDependencyContext = CreateLookupFunction<string, string>((c, a) => ValueOrProceed<string>.Proceed());
var loadFromRemote = CreateLookupFunction<string, string>((c, a) => ValueOrProceed<string>.FromValue(someAssemblyName.Name, false));
var loadFromAppDomain = CreateLookupFunction<string, IntPtr>((c, a) => ValueOrProceed<IntPtr>.Proceed());
var result = sut.LoadUnmanagedDll(initialPluginLoadDirectory, someAssemblyName.Name, pluginDependencyContext.Object, loadFromDependencyContext, loadFromRemote, loadFromAppDomain);
Assert.AreEqual(someAssemblyName.Name, result.Path);
Assert.AreEqual(IntPtr.Zero, result.Pointer);
}
protected Func<string, AssemblyName, ValueOrProceed<AssemblyFromStrategy>> CreateLookupFunction(Func<string, AssemblyName, ValueOrProceed<AssemblyFromStrategy>> func) => func;
protected Func<string, AssemblyName, ValueOrProceed<RuntimeAssemblyShim>> CreateLookupFunction(Func<string, AssemblyName, ValueOrProceed<RuntimeAssemblyShim>> func) => func;
protected Func<string, T1, ValueOrProceed<T2>> CreateLookupFunction<T1, T2>(Func<string, T1, ValueOrProceed<T2>> func) => func;
}
}