Fun with assembly loading
This commit is contained in:
parent
0f86642524
commit
c995732f35
|
@ -4,7 +4,7 @@ using Logging;
|
||||||
|
|
||||||
namespace CodexPlugin
|
namespace CodexPlugin
|
||||||
{
|
{
|
||||||
public class Plugin : IProjectPlugin
|
public class CodexPlugin : IProjectPlugin
|
||||||
{
|
{
|
||||||
private CodexStarter codexStarter = null!;
|
private CodexStarter codexStarter = null!;
|
||||||
|
|
||||||
|
@ -18,8 +18,6 @@ namespace CodexPlugin
|
||||||
public void Initialize(IPluginTools tools)
|
public void Initialize(IPluginTools tools)
|
||||||
{
|
{
|
||||||
codexStarter = new CodexStarter(tools);
|
codexStarter = new CodexStarter(tools);
|
||||||
|
|
||||||
DistTestExtensions.Plugin = this;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Finalize(ILog log)
|
public void Finalize(ILog log)
|
|
@ -1,30 +0,0 @@
|
||||||
using DistTestCore;
|
|
||||||
using KubernetesWorkflow;
|
|
||||||
|
|
||||||
namespace CodexPlugin
|
|
||||||
{
|
|
||||||
public static class DistTestExtensions
|
|
||||||
{
|
|
||||||
public static Plugin Plugin { get; internal set; } = null!;
|
|
||||||
|
|
||||||
public static RunningContainers[] StartCodexNodes(this DistTest distTest, int number, Action<ICodexSetup> setup)
|
|
||||||
{
|
|
||||||
return Plugin.StartCodexNodes(number, setup);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static ICodexNodeGroup WrapCodexContainers(this DistTest distTest, RunningContainers[] containers)
|
|
||||||
{
|
|
||||||
return Plugin.WrapCodexContainers(containers);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static IOnlineCodexNode SetupCodexNode(this DistTest distTest, Action<ICodexSetup> setup)
|
|
||||||
{
|
|
||||||
return Plugin.SetupCodexNode(setup);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static ICodexNodeGroup SetupCodexNodes(this DistTest distTest, int number)
|
|
||||||
{
|
|
||||||
return Plugin.SetupCodexNodes(number);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,33 @@
|
||||||
|
using DistTestCore;
|
||||||
|
using KubernetesWorkflow;
|
||||||
|
|
||||||
|
namespace CodexPlugin
|
||||||
|
{
|
||||||
|
public static class PluginInterfaceExtensions
|
||||||
|
{
|
||||||
|
public static RunningContainers[] StartCodexNodes(this PluginInterface pluginInterface, int number, Action<ICodexSetup> setup)
|
||||||
|
{
|
||||||
|
return Plugin(pluginInterface).StartCodexNodes(number, setup);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ICodexNodeGroup WrapCodexContainers(this PluginInterface pluginInterface, RunningContainers[] containers)
|
||||||
|
{
|
||||||
|
return Plugin(pluginInterface).WrapCodexContainers(containers);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IOnlineCodexNode SetupCodexNode(this PluginInterface pluginInterface, Action<ICodexSetup> setup)
|
||||||
|
{
|
||||||
|
return Plugin(pluginInterface).SetupCodexNode(setup);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ICodexNodeGroup SetupCodexNodes(this PluginInterface pluginInterface, int number)
|
||||||
|
{
|
||||||
|
return Plugin(pluginInterface).SetupCodexNodes(number);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static CodexPlugin Plugin(PluginInterface pluginInterface)
|
||||||
|
{
|
||||||
|
return pluginInterface.GetPlugin<CodexPlugin>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -9,7 +9,7 @@ using Utils;
|
||||||
namespace DistTestCore
|
namespace DistTestCore
|
||||||
{
|
{
|
||||||
[Parallelizable(ParallelScope.All)]
|
[Parallelizable(ParallelScope.All)]
|
||||||
public abstract class DistTest
|
public abstract class DistTest : PluginInterface
|
||||||
{
|
{
|
||||||
private const string TestsType = "dist-tests";
|
private const string TestsType = "dist-tests";
|
||||||
private readonly Configuration configuration = new Configuration();
|
private readonly Configuration configuration = new Configuration();
|
||||||
|
@ -153,6 +153,11 @@ namespace DistTestCore
|
||||||
// return Get().CodexStarter.RunningGroups.SelectMany(g => g.Nodes);
|
// return Get().CodexStarter.RunningGroups.SelectMany(g => g.Nodes);
|
||||||
//}
|
//}
|
||||||
|
|
||||||
|
public override T GetPlugin<T>()
|
||||||
|
{
|
||||||
|
return Get().GetPlugin<T>();
|
||||||
|
}
|
||||||
|
|
||||||
private void AnnouncePlugins(FixtureLog fixtureLog)
|
private void AnnouncePlugins(FixtureLog fixtureLog)
|
||||||
{
|
{
|
||||||
PluginManager.AnnouncePlugins(fixtureLog);
|
PluginManager.AnnouncePlugins(fixtureLog);
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
namespace DistTestCore
|
||||||
|
{
|
||||||
|
public abstract class PluginInterface
|
||||||
|
{
|
||||||
|
public abstract T GetPlugin<T>() where T : IProjectPlugin;
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,6 +1,7 @@
|
||||||
using FileUtils;
|
using FileUtils;
|
||||||
using KubernetesWorkflow;
|
using KubernetesWorkflow;
|
||||||
using Logging;
|
using Logging;
|
||||||
|
using System.Reflection;
|
||||||
using Utils;
|
using Utils;
|
||||||
|
|
||||||
namespace DistTestCore
|
namespace DistTestCore
|
||||||
|
@ -34,6 +35,11 @@ namespace DistTestCore
|
||||||
{
|
{
|
||||||
foreach (var plugin in projectPlugins) plugin.Finalize(log);
|
foreach (var plugin in projectPlugins) plugin.Finalize(log);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public T GetPlugin<T>() where T : IProjectPlugin
|
||||||
|
{
|
||||||
|
return (T)projectPlugins.Single(p => p.GetType() == typeof(T));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class PluginFinder
|
public static class PluginFinder
|
||||||
|
@ -45,10 +51,37 @@ namespace DistTestCore
|
||||||
if (pluginTypes != null) return pluginTypes;
|
if (pluginTypes != null) return pluginTypes;
|
||||||
|
|
||||||
// Reflection can be costly. Do this only once.
|
// Reflection can be costly. Do this only once.
|
||||||
|
FindAndLoadPluginAssemblies();
|
||||||
|
|
||||||
var assemblies = AppDomain.CurrentDomain.GetAssemblies();
|
var assemblies = AppDomain.CurrentDomain.GetAssemblies();
|
||||||
pluginTypes = assemblies.SelectMany(a => a.GetTypes().Where(t => typeof(IProjectPlugin).IsAssignableFrom(t))).ToArray();
|
pluginTypes = assemblies.SelectMany(a => a.GetTypes().Where(t =>
|
||||||
|
typeof(IProjectPlugin).IsAssignableFrom(t) &&
|
||||||
|
!t.IsAbstract)
|
||||||
|
).ToArray();
|
||||||
|
|
||||||
return pluginTypes;
|
return pluginTypes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void FindAndLoadPluginAssemblies()
|
||||||
|
{
|
||||||
|
var files = Directory.GetFiles(".");
|
||||||
|
foreach (var file in files)
|
||||||
|
{
|
||||||
|
var f = file.ToLowerInvariant();
|
||||||
|
if (f.Contains("plugin") && f.EndsWith("dll"))
|
||||||
|
{
|
||||||
|
var name = Path.GetFileNameWithoutExtension(file);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Assembly.Load(name);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
throw new Exception($"Failed to load plugin from file '{name}'.", ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public interface IProjectPlugin
|
public interface IProjectPlugin
|
||||||
|
|
|
@ -32,6 +32,11 @@ namespace DistTestCore
|
||||||
public string TestNamespace { get; }
|
public string TestNamespace { get; }
|
||||||
public IFileManager FileManager { get; }
|
public IFileManager FileManager { get; }
|
||||||
|
|
||||||
|
public T GetPlugin<T>() where T : IProjectPlugin
|
||||||
|
{
|
||||||
|
return pluginManager.GetPlugin<T>();
|
||||||
|
}
|
||||||
|
|
||||||
public Http CreateHttp(Address address, string baseUrl, Action<HttpClient> onClientCreated, string? logAlias = null)
|
public Http CreateHttp(Address address, string baseUrl, Action<HttpClient> onClientCreated, string? logAlias = null)
|
||||||
{
|
{
|
||||||
return new Http(Log, TimeSet, address, baseUrl, onClientCreated, logAlias);
|
return new Http(Log, TimeSet, address, baseUrl, onClientCreated, logAlias);
|
||||||
|
|
|
@ -0,0 +1,19 @@
|
||||||
|
namespace Logging
|
||||||
|
{
|
||||||
|
public abstract class BaseTestLog : BaseLog
|
||||||
|
{
|
||||||
|
private bool hasFailed;
|
||||||
|
|
||||||
|
public BaseTestLog(bool debug)
|
||||||
|
: base(debug)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public void MarkAsFailed()
|
||||||
|
{
|
||||||
|
if (hasFailed) return;
|
||||||
|
hasFailed = true;
|
||||||
|
LogFile.ConcatToFilename("_FAILED");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,12 +1,12 @@
|
||||||
namespace Logging
|
namespace Logging
|
||||||
{
|
{
|
||||||
public class FixtureLog : TestLog
|
public class FixtureLog : BaseTestLog
|
||||||
{
|
{
|
||||||
private readonly string fullName;
|
private readonly string fullName;
|
||||||
private readonly LogConfig config;
|
private readonly LogConfig config;
|
||||||
|
|
||||||
public FixtureLog(LogConfig config, DateTime start, string name = "")
|
public FixtureLog(LogConfig config, DateTime start, string name = "")
|
||||||
: base(config.LogRoot, config.DebugEnabled)
|
: base(config.DebugEnabled)
|
||||||
{
|
{
|
||||||
fullName = NameUtils.GetFixtureFullName(config, start, name);
|
fullName = NameUtils.GetFixtureFullName(config, start, name);
|
||||||
this.config = config;
|
this.config = config;
|
||||||
|
|
|
@ -1,10 +1,9 @@
|
||||||
namespace Logging
|
namespace Logging
|
||||||
{
|
{
|
||||||
public class TestLog : BaseLog
|
public class TestLog : BaseTestLog
|
||||||
{
|
{
|
||||||
private readonly string methodName;
|
private readonly string methodName;
|
||||||
private readonly string fullName;
|
private readonly string fullName;
|
||||||
private bool hasFailed;
|
|
||||||
|
|
||||||
public TestLog(string folder, bool debug, string name = "")
|
public TestLog(string folder, bool debug, string name = "")
|
||||||
: base(debug)
|
: base(debug)
|
||||||
|
@ -15,13 +14,6 @@
|
||||||
Log($"*** Begin: {methodName}");
|
Log($"*** Begin: {methodName}");
|
||||||
}
|
}
|
||||||
|
|
||||||
public void MarkAsFailed()
|
|
||||||
{
|
|
||||||
if (hasFailed) return;
|
|
||||||
hasFailed = true;
|
|
||||||
LogFile.ConcatToFilename("_FAILED");
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override string GetFullName()
|
protected override string GetFullName()
|
||||||
{
|
{
|
||||||
return fullName;
|
return fullName;
|
||||||
|
|
Loading…
Reference in New Issue