Better logging alignment for continous tests

This commit is contained in:
benbierens 2023-06-21 10:06:54 +02:00
parent 978d2d3a84
commit c5c54f5963
No known key found for this signature in database
GPG Key ID: FE44815D96D0A1AA
6 changed files with 102 additions and 55 deletions

View File

@ -1,64 +1,86 @@
using DistTestCore; using DistTestCore;
using DistTestCore.Codex; using DistTestCore.Codex;
using Logging; using Logging;
using Utils;
namespace ContinuousTests namespace ContinuousTests
{ {
public class TestRun public class AllTestsRun
{ {
private readonly Random random = new Random();
private readonly CodexNodeFactory codexNodeFactory = new CodexNodeFactory();
private readonly Configuration config; private readonly Configuration config;
private readonly BaseLog log; private readonly FixtureLog log;
private readonly TestFactory testFinder; private readonly TestFactory testFinder;
private readonly FileManager fileManager;
private ITimeSet timeSet;
public TestRun(Configuration config, BaseLog log, TestFactory testFinder) public AllTestsRun(Configuration config, FixtureLog log, TestFactory testFinder)
{ {
this.config = config; this.config = config;
this.log = log; this.log = log;
this.testFinder = testFinder; this.testFinder = testFinder;
fileManager = new FileManager(log, new DistTestCore.Configuration());
timeSet = new DefaultTimeSet();
} }
public void Run() public ContinuousTestResult RunAll()
{ {
var remainingTests = testFinder.CreateTests().ToList(); var remainingTests = testFinder.CreateTests().ToList();
var result = ContinuousTestResult.Passed;
while (remainingTests.Any()) while (remainingTests.Any())
{ {
var test = PickOneRandom(remainingTests); var test = remainingTests.PickOneRandom();
var nodes = CreateRandomNodes(test.RequiredNumberOfNodes); var testLog = log.CreateTestLog(test.Name);
AssignEssentials(test, nodes); var singleTestRun = new SingleTestRun(config, test, testLog);
fileManager.PushFileSet();
log.Log($"Start '{test.Name}'"); log.Log($"Start '{test.Name}'");
try try
{ {
test.Run(); singleTestRun.Run();
log.Log($"'{test.Name}' = Passed"); log.Log($"'{test.Name}' = Passed");
} }
catch catch
{ {
log.Log($"'{test.Name}' = Failed"); log.Log($"'{test.Name}' = Failed");
testLog.MarkAsFailed();
result = ContinuousTestResult.Failed;
} }
fileManager.PopFileSet();
ClearEssentials(test);
Thread.Sleep(config.SleepSecondsPerTest * 1000); Thread.Sleep(config.SleepSecondsPerTest * 1000);
} }
return result;
}
}
public class SingleTestRun
{
private readonly CodexNodeFactory codexNodeFactory = new CodexNodeFactory();
private readonly Configuration config;
private readonly ContinuousTest test;
private readonly CodexNode[] nodes;
private readonly FileManager fileManager;
public SingleTestRun(Configuration config, ContinuousTest test, BaseLog testLog)
{
this.config = config;
this.test = test;
nodes = CreateRandomNodes(test.RequiredNumberOfNodes, testLog);
fileManager = new FileManager(testLog, new DistTestCore.Configuration());
test.Initialize(nodes, testLog, fileManager);
} }
private void AssignEssentials(ContinuousTest test, CodexNode[] nodes) public void Run()
{ {
test.Initialize(nodes, log, fileManager); test.Run();
} }
private void ClearEssentials(ContinuousTest test) public void TearDown()
{ {
// Looks a little strange, but prevents finished test from interacting further.
test.Initialize(null!, null!, null!); test.Initialize(null!, null!, null!);
fileManager.DeleteAllTestFiles();
}
private CodexNode[] CreateRandomNodes(int number, BaseLog testLog)
{
var urls = SelectRandomUrls(number);
return codexNodeFactory.Create(urls, testLog, test.TimeSet);
} }
private string[] SelectRandomUrls(int number) private string[] SelectRandomUrls(int number)
@ -67,23 +89,9 @@ namespace ContinuousTests
var result = new string[number]; var result = new string[number];
for (var i = 0; i < number; i++) for (var i = 0; i < number; i++)
{ {
result[i] = PickOneRandom(urls); result[i] = urls.PickOneRandom();
} }
return result; return result;
} }
private CodexNode[] CreateRandomNodes(int number)
{
var urls = SelectRandomUrls(number);
return codexNodeFactory.Create(urls, log, timeSet);
}
private T PickOneRandom<T>(List<T> remainingItems)
{
var i = random.Next(0, remainingItems.Count);
var result = remainingItems[i];
remainingItems.RemoveAt(i);
return result;
}
} }
} }

View File

@ -16,6 +16,10 @@ namespace ContinuousTests
public Configuration Load() public Configuration Load()
{ {
var config = Read(); var config = Read();
//config.LogPath = "logs";
//config.SleepSecondsPerTest = 10;
//config.CodexUrls = new string[] { "http://localhost:8080", "http://localhost:8081" };
Validate(config); Validate(config);
return config; return config;
} }

View File

@ -13,33 +13,43 @@ namespace ContinuousTests
public void Run() public void Run()
{ {
var config = configLoader.Load(); var config = configLoader.Load();
var log = new TestLog(config.LogPath, true); StartupChecks(config);
log.Log("Starting continuous test run...");
log.Log("Checking configuration...");
PreflightCheck(config);
log.Log("Contacting Codex nodes...");
CheckCodexNodes(log, config);
log.Log("All OK.");
log.Log("");
while (true) while (true)
{ {
var run = new TestRun(config, log, testFactory); var log = new FixtureLog(new LogConfig(config.LogPath, false), "StartupChecks");
var allTestsRun = new AllTestsRun(config, log, testFactory);
var result = ContinuousTestResult.Passed;
try try
{ {
run.Run(); result = allTestsRun.RunAll();
} }
catch (Exception ex) catch (Exception ex)
{ {
log.Error($"Exception during test run: " + ex); log.Error($"Exception during test run: " + ex);
} }
if (result == ContinuousTestResult.Failed)
{
log.MarkAsFailed();
}
Thread.Sleep(config.SleepSecondsPerTest * 1000); Thread.Sleep(config.SleepSecondsPerTest * 1000);
} }
} }
private void StartupChecks(Configuration config)
{
var log = new FixtureLog(new LogConfig(config.LogPath, false), "ContinuousTestsRun");
log.Log("Starting continuous test run...");
log.Log("Checking configuration...");
PreflightCheck(config);
log.Log("Contacting Codex nodes...");
CheckCodexNodes(log, config);
log.Log("All OK.");
}
private void PreflightCheck(Configuration config) private void PreflightCheck(Configuration config)
{ {
var tests = testFactory.CreateTests(); var tests = testFactory.CreateTests();
@ -106,4 +116,10 @@ namespace ContinuousTests
return true; return true;
} }
} }
public enum ContinuousTestResult
{
Passed,
Failed
}
} }

View File

@ -8,19 +8,19 @@ namespace Logging
private readonly string fullName; private readonly string fullName;
private readonly LogConfig config; private readonly LogConfig config;
public FixtureLog(LogConfig config) public FixtureLog(LogConfig config, string name = "")
: base(config.DebugEnabled) : base(config.DebugEnabled)
{ {
start = DateTime.UtcNow; start = DateTime.UtcNow;
var folder = DetermineFolder(config); var folder = DetermineFolder(config);
var fixtureName = GetFixtureName(); var fixtureName = GetFixtureName(name);
fullName = Path.Combine(folder, fixtureName); fullName = Path.Combine(folder, fixtureName);
this.config = config; this.config = config;
} }
public TestLog CreateTestLog() public TestLog CreateTestLog(string name = "")
{ {
return new TestLog(fullName, config.DebugEnabled); return new TestLog(fullName, config.DebugEnabled, name);
} }
protected override LogFile CreateLogFile() protected override LogFile CreateLogFile()
@ -36,10 +36,12 @@ namespace Logging
Pad(start.Day)); Pad(start.Day));
} }
private string GetFixtureName() private string GetFixtureName(string name)
{ {
var test = TestContext.CurrentContext.Test; var test = TestContext.CurrentContext.Test;
var className = test.ClassName!.Substring(test.ClassName.LastIndexOf('.') + 1); var className = test.ClassName!.Substring(test.ClassName.LastIndexOf('.') + 1);
if (!string.IsNullOrEmpty(name)) className = name;
return $"{Pad(start.Hour)}-{Pad(start.Minute)}-{Pad(start.Second)}Z_{className.Replace('.', '-')}"; return $"{Pad(start.Hour)}-{Pad(start.Minute)}-{Pad(start.Second)}Z_{className.Replace('.', '-')}";
} }

View File

@ -9,10 +9,10 @@ namespace Logging
private readonly string methodName; private readonly string methodName;
private readonly string fullName; private readonly string fullName;
public TestLog(string folder, bool debug) public TestLog(string folder, bool debug, string name = "")
: base(debug) : base(debug)
{ {
methodName = GetMethodName(); methodName = GetMethodName(name);
fullName = Path.Combine(folder, methodName); fullName = Path.Combine(folder, methodName);
Log($"*** Begin: {methodName}"); Log($"*** Begin: {methodName}");
@ -39,13 +39,15 @@ namespace Logging
MarkAsFailed(); MarkAsFailed();
} }
} }
protected override LogFile CreateLogFile() protected override LogFile CreateLogFile()
{ {
return new LogFile(fullName, "log"); return new LogFile(fullName, "log");
} }
private string GetMethodName() private string GetMethodName(string name)
{ {
if (!string.IsNullOrEmpty(name)) return name;
var test = TestContext.CurrentContext.Test; var test = TestContext.CurrentContext.Test;
var args = FormatArguments(test); var args = FormatArguments(test);
return $"{test.MethodName}{args}"; return $"{test.MethodName}{args}";

15
Utils/RandomUtils.cs Normal file
View File

@ -0,0 +1,15 @@
namespace Utils
{
public static class RandomUtils
{
private static readonly Random random = new Random();
public static T PickOneRandom<T>(this List<T> remainingItems)
{
var i = random.Next(0, remainingItems.Count);
var result = remainingItems[i];
remainingItems.RemoveAt(i);
return result;
}
}
}