Restores continuous test runner.

This commit is contained in:
benbierens 2023-09-21 10:33:09 +02:00
parent b5e0c9bfe0
commit dbf0ed714c
No known key found for this signature in database
GPG Key ID: FE44815D96D0A1AA
14 changed files with 153 additions and 74 deletions

View File

@ -38,9 +38,10 @@ namespace Core
return new CoreInterface(this);
}
public void Decommission()
public void Decommission(bool deleteKubernetesResources, bool deleteTrackedFiles)
{
manager.DecommissionPlugins();
manager.DecommissionPlugins(deleteKubernetesResources, deleteTrackedFiles);
Tools.Decommission(deleteKubernetesResources, deleteTrackedFiles);
}
internal T GetPlugin<T>() where T : IProjectPlugin

View File

@ -2,11 +2,11 @@
{
internal class PluginManager
{
private readonly List<IProjectPlugin> projectPlugins = new List<IProjectPlugin>();
private readonly List<PluginToolsPair> pairs = new List<PluginToolsPair>();
internal void InstantiatePlugins(Type[] pluginTypes, IToolsFactory provider)
{
projectPlugins.Clear();
pairs.Clear();
foreach (var pluginType in pluginTypes)
{
var tools = provider.CreateTools();
@ -18,15 +18,15 @@
internal void AnnouncePlugins()
{
foreach (var plugin in projectPlugins) plugin.Announce();
foreach (var pair in pairs) pair.Plugin.Announce();
}
internal PluginMetadata GatherPluginMetadata()
{
var metadata = new PluginMetadata();
foreach (var plugin in projectPlugins)
foreach (var pair in pairs)
{
if (plugin is IHasMetadata m)
if (pair.Plugin is IHasMetadata m)
{
m.AddMetadata(metadata);
}
@ -34,20 +34,24 @@
return metadata;
}
internal void DecommissionPlugins()
internal void DecommissionPlugins(bool deleteKubernetesResources, bool deleteTrackedFiles)
{
foreach (var plugin in projectPlugins) plugin.Decommission();
foreach (var pair in pairs)
{
pair.Plugin.Decommission();
pair.Tools.Decommission(deleteKubernetesResources, deleteTrackedFiles);
}
}
internal T GetPlugin<T>() where T : IProjectPlugin
{
return (T)projectPlugins.Single(p => p.GetType() == typeof(T));
return (T)pairs.Single(p => p.Plugin.GetType() == typeof(T)).Plugin;
}
private IProjectPlugin InstantiatePlugins(Type pluginType, PluginTools tools)
{
var plugin = (IProjectPlugin)Activator.CreateInstance(pluginType, args: tools)!;
projectPlugins.Add(plugin);
pairs.Add(new PluginToolsPair(plugin, tools));
return plugin;
}
@ -58,5 +62,17 @@
tools.ApplyLogPrefix(hasLogPrefix.LogPrefix);
}
}
private class PluginToolsPair
{
public PluginToolsPair(IProjectPlugin plugin, IPluginTools tools)
{
Plugin = plugin;
Tools = tools;
}
public IProjectPlugin Plugin { get; }
public IPluginTools Tools { get; }
}
}
}

View File

@ -7,6 +7,7 @@ namespace Core
{
public interface IPluginTools : IWorkflowTool, ILogTool, IHttpFactoryTool, IFileTool
{
void Decommission(bool deleteKubernetesResources, bool deleteTrackedFiles);
}
public interface IWorkflowTool
@ -65,6 +66,12 @@ namespace Core
return workflowCreator.CreateWorkflow(namespaceOverride);
}
public void Decommission(bool deleteKubernetesResources, bool deleteTrackedFiles)
{
if (deleteKubernetesResources) CreateWorkflow().DeleteNamespace();
if (deleteTrackedFiles) fileManager.DeleteAllFiles();
}
public IFileManager GetFileManager()
{
return fileManager;

View File

@ -18,6 +18,7 @@ namespace FileUtils
private static NumberSource folderNumberSource = new NumberSource(0);
private readonly Random random = new Random();
private readonly ILog log;
private readonly string rootFolder;
private readonly string folder;
private readonly List<List<TrackedFile>> fileSetStack = new List<List<TrackedFile>>();
@ -25,13 +26,15 @@ namespace FileUtils
{
folder = Path.Combine(rootFolder, folderNumberSource.GetNextNumber().ToString("D5"));
EnsureDirectory();
this.log = log;
this.rootFolder = rootFolder;
}
public TrackedFile CreateEmptyFile(string label = "")
{
var path = Path.Combine(folder, Guid.NewGuid().ToString() + "_test.bin");
var path = Path.Combine(folder, Guid.NewGuid().ToString() + ".bin");
EnsureDirectory();
var result = new TrackedFile(log, path, label);
File.Create(result.Filename).Close();
if (fileSetStack.Any()) fileSetStack.Last().Add(result);
@ -79,12 +82,11 @@ namespace FileUtils
foreach (var file in pop)
{
try
{
File.Delete(file.Filename);
}
catch { }
File.Delete(file.Filename);
}
// If the folder is now empty, delete it too.
if (!Directory.GetFiles(folder).Any()) DeleteDirectory();
}
private TrackedFile GenerateRandomFile(ByteSize size, string label)
@ -144,12 +146,12 @@ namespace FileUtils
private void EnsureDirectory()
{
if (!Directory.Exists(folder)) Directory.CreateDirectory(folder);
Directory.CreateDirectory(folder);
}
private void DeleteDirectory()
{
Directory.Delete(folder, true);
if (Directory.Exists(folder)) Directory.Delete(folder, true);
}
}
}

View File

@ -0,0 +1,19 @@
namespace Logging
{
public class ConsoleLog : BaseLog
{
public ConsoleLog() : base(false)
{
}
protected override string GetFullName()
{
return "CONSOLE";
}
public override void Log(string message)
{
Console.WriteLine(message);
}
}
}

View File

@ -0,0 +1,42 @@
namespace Logging
{
public class LogSplitter : ILog
{
private readonly ILog[] targetLogs;
public LogSplitter(params ILog[] targetLogs)
{
this.targetLogs = targetLogs;
}
public void AddStringReplace(string from, string to)
{
OnAll(l => l.AddStringReplace(from, to));
}
public LogFile CreateSubfile(string ext = "log")
{
return targetLogs.First().CreateSubfile(ext);
}
public void Debug(string message = "", int skipFrames = 0)
{
OnAll(l => l.Debug(message, skipFrames + 2));
}
public void Error(string message)
{
OnAll(l => l.Error(message));
}
public void Log(string message)
{
OnAll(l => l.Log(message));
}
private void OnAll(Action<ILog> action)
{
foreach (var t in targetLogs) action(t);
}
}
}

View File

@ -59,7 +59,6 @@ namespace ContinuousTests
return GetType().Name;
}
}
}
public enum TestFailMode

View File

@ -19,21 +19,29 @@ namespace ContinuousTests
public void Run()
{
var overviewLog = new FixtureLog(new LogConfig(config.LogPath, false), DateTime.UtcNow, "Overview");
var overviewLog = new LogSplitter(
new FixtureLog(new LogConfig(config.LogPath, false), DateTime.UtcNow, "Overview"),
new ConsoleLog()
);
overviewLog.Log("Initializing...");
var entryPoint = entryPointFactory.CreateEntryPoint(config.KubeConfigFile, config.DataPath, config.CodexDeployment.Metadata.KubeNamespace, overviewLog);
entryPoint.Announce();
overviewLog.Log("Initialized. Performing startup checks...");
var startupChecker = new StartupChecker(entryPoint, config, cancelToken);
startupChecker.Check();
var taskFactory = new TaskFactory();
overviewLog.Log("Continuous tests starting...");
overviewLog.Log("Startup checks passed. Continuous tests starting...");
overviewLog.Log("");
var allTests = testFactory.CreateTests();
ClearAllCustomNamespaces(allTests, overviewLog);
var testLoops = allTests.Select(t => new TestLoop(entryPoint, taskFactory, config, overviewLog, t.GetType(), t.RunTestEvery, startupChecker, cancelToken)).ToArray();
var testLoops = allTests.Select(t => new TestLoop(entryPointFactory, taskFactory, config, overviewLog, t.GetType(), t.RunTestEvery, startupChecker, cancelToken)).ToArray();
foreach (var testLoop in testLoops)
{
@ -51,12 +59,12 @@ namespace ContinuousTests
overviewLog.Log("All tasks cancelled.");
}
private void ClearAllCustomNamespaces(ContinuousTest[] allTests, FixtureLog log)
private void ClearAllCustomNamespaces(ContinuousTest[] allTests, ILog log)
{
foreach (var test in allTests) ClearAllCustomNamespaces(test, log);
}
private void ClearAllCustomNamespaces(ContinuousTest test, FixtureLog log)
private void ClearAllCustomNamespaces(ContinuousTest test, ILog log)
{
if (string.IsNullOrEmpty(test.CustomK8sNamespace)) return;

View File

@ -5,7 +5,6 @@ public class Program
public static void Main(string[] args)
{
Console.WriteLine("Codex Continous-Test-Runner.");
Console.WriteLine("Running...");
var runner = new ContinuousTestRunner(args, Cancellation.Cts.Token);
@ -20,14 +19,14 @@ public class Program
runner.Run();
Console.WriteLine("Done.");
}
public static class Cancellation
{
static Cancellation()
{
Cts = new CancellationTokenSource();
}
public static CancellationTokenSource Cts { get; }
}
}
public static class Cancellation
{
static Cancellation()
{
Cts = new CancellationTokenSource();
}
public static CancellationTokenSource Cts { get; }
}

View File

@ -3,8 +3,6 @@ using Utils;
using KubernetesWorkflow;
using NUnit.Framework.Internal;
using System.Reflection;
using static Program;
using FileUtils;
using CodexPlugin;
using DistTestCore.Logs;
using Core;
@ -17,18 +15,16 @@ namespace ContinuousTests
private readonly EntryPoint entryPoint;
private readonly TaskFactory taskFactory;
private readonly Configuration config;
private readonly BaseLog overviewLog;
private readonly ILog overviewLog;
private readonly TestHandle handle;
private readonly CancellationToken cancelToken;
private readonly ICodexNode[] nodes;
private readonly FixtureLog fixtureLog;
private readonly string testName;
private readonly string dataFolder;
private static int failureCount = 0;
public SingleTestRun(EntryPoint entryPoint, TaskFactory taskFactory, Configuration config, BaseLog overviewLog, TestHandle handle, StartupChecker startupChecker, CancellationToken cancelToken)
public SingleTestRun(EntryPointFactory entryPointFactory, TaskFactory taskFactory, Configuration config, ILog overviewLog, TestHandle handle, StartupChecker startupChecker, CancellationToken cancelToken)
{
this.entryPoint = entryPoint;
this.taskFactory = taskFactory;
this.config = config;
this.overviewLog = overviewLog;
@ -36,10 +32,10 @@ namespace ContinuousTests
this.cancelToken = cancelToken;
testName = handle.Test.GetType().Name;
fixtureLog = new FixtureLog(new LogConfig(config.LogPath, true), DateTime.UtcNow, testName);
entryPoint = entryPointFactory.CreateEntryPoint(config.KubeConfigFile, config.DataPath, config.CodexDeployment.Metadata.KubeNamespace, fixtureLog);
ApplyLogReplacements(fixtureLog, startupChecker);
nodes = CreateRandomNodes();
dataFolder = config.DataPath + "-" + Guid.NewGuid();
}
public void Run(EventWaitHandle runFinishedHandle)
@ -49,8 +45,11 @@ namespace ContinuousTests
try
{
RunTest();
entryPoint.Tools.GetFileManager().DeleteAllFiles();
Directory.Delete(dataFolder, true);
entryPoint.Decommission(
deleteKubernetesResources: false, // This would delete the continuous test net.
deleteTrackedFiles: true
);
runFinishedHandle.Set();
}
catch (Exception ex)

View File

@ -1,23 +1,22 @@
using Core;
using Logging;
using Logging;
namespace ContinuousTests
{
public class TestLoop
{
private readonly EntryPoint entryPoint;
private readonly EntryPointFactory entryPointFactory;
private readonly TaskFactory taskFactory;
private readonly Configuration config;
private readonly BaseLog overviewLog;
private readonly ILog overviewLog;
private readonly Type testType;
private readonly TimeSpan runsEvery;
private readonly StartupChecker startupChecker;
private readonly CancellationToken cancelToken;
private readonly EventWaitHandle runFinishedHandle = new EventWaitHandle(true, EventResetMode.ManualReset);
public TestLoop(Core.EntryPoint entryPoint, TaskFactory taskFactory, Configuration config, BaseLog overviewLog, Type testType, TimeSpan runsEvery, StartupChecker startupChecker, CancellationToken cancelToken)
public TestLoop(EntryPointFactory entryPointFactory, TaskFactory taskFactory, Configuration config, ILog overviewLog, Type testType, TimeSpan runsEvery, StartupChecker startupChecker, CancellationToken cancelToken)
{
this.entryPoint = entryPoint;
this.entryPointFactory = entryPointFactory;
this.taskFactory = taskFactory;
this.config = config;
this.overviewLog = overviewLog;
@ -63,7 +62,7 @@ namespace ContinuousTests
{
var test = (ContinuousTest)Activator.CreateInstance(testType)!;
var handle = new TestHandle(test);
var run = new SingleTestRun(entryPoint, taskFactory, config, overviewLog, handle, startupChecker, cancelToken);
var run = new SingleTestRun(entryPointFactory, taskFactory, config, overviewLog, handle, startupChecker, cancelToken);
runFinishedHandle.Reset();
run.Run(runFinishedHandle);

View File

@ -62,7 +62,11 @@ namespace DistTestCore
[OneTimeTearDown]
public void GlobalTearDown()
{
globalEntryPoint.Decommission();
globalEntryPoint.Decommission(
// There shouldn't be any of either, but clean everything up regardless.
deleteKubernetesResources: true,
deleteTrackedFiles: true
);
}
[SetUp]

View File

@ -33,9 +33,10 @@ namespace DistTestCore
public void DeleteAllResources()
{
entryPoint.Tools.CreateWorkflow().DeleteNamespace();
entryPoint.Tools.GetFileManager().DeleteAllFiles();
entryPoint.Decommission();
entryPoint.Decommission(
deleteKubernetesResources: true,
deleteTrackedFiles: true
);
}
public TrackedFile GenerateTestFile(ByteSize size, string label = "")

View File

@ -14,21 +14,4 @@ namespace CodexNetDeployer
checker.AssertFullyConnected(nodes);
}
}
public class ConsoleLog : BaseLog
{
public ConsoleLog() : base(false)
{
}
protected override string GetFullName()
{
return "CONSOLE";
}
public override void Log(string message)
{
Console.WriteLine(message);
}
}
}