From c5c54f5963e0fd258eb58a95b7dfd48af0606942 Mon Sep 17 00:00:00 2001 From: benbierens Date: Wed, 21 Jun 2023 10:06:54 +0200 Subject: [PATCH] Better logging alignment for continous tests --- .../{TestRun.cs => AllTestsRun.cs} | 80 ++++++++++--------- ContinuousTests/Configuration.cs | 4 + ContinuousTests/ContinuousTestRunner.cs | 38 ++++++--- Logging/FixtureLog.cs | 12 +-- Logging/TestLog.cs | 8 +- Utils/RandomUtils.cs | 15 ++++ 6 files changed, 102 insertions(+), 55 deletions(-) rename ContinuousTests/{TestRun.cs => AllTestsRun.cs} (50%) create mode 100644 Utils/RandomUtils.cs diff --git a/ContinuousTests/TestRun.cs b/ContinuousTests/AllTestsRun.cs similarity index 50% rename from ContinuousTests/TestRun.cs rename to ContinuousTests/AllTestsRun.cs index 43e71b0..3fc0d4a 100644 --- a/ContinuousTests/TestRun.cs +++ b/ContinuousTests/AllTestsRun.cs @@ -1,64 +1,86 @@ using DistTestCore; using DistTestCore.Codex; using Logging; +using Utils; 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 BaseLog log; + private readonly FixtureLog log; 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.log = log; 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 result = ContinuousTestResult.Passed; while (remainingTests.Any()) { - var test = PickOneRandom(remainingTests); - var nodes = CreateRandomNodes(test.RequiredNumberOfNodes); - AssignEssentials(test, nodes); - fileManager.PushFileSet(); + var test = remainingTests.PickOneRandom(); + var testLog = log.CreateTestLog(test.Name); + var singleTestRun = new SingleTestRun(config, test, testLog); log.Log($"Start '{test.Name}'"); try { - test.Run(); + singleTestRun.Run(); log.Log($"'{test.Name}' = Passed"); } catch { log.Log($"'{test.Name}' = Failed"); + testLog.MarkAsFailed(); + result = ContinuousTestResult.Failed; } - fileManager.PopFileSet(); - ClearEssentials(test); 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!); + 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) @@ -67,23 +89,9 @@ namespace ContinuousTests var result = new string[number]; for (var i = 0; i < number; i++) { - result[i] = PickOneRandom(urls); + result[i] = urls.PickOneRandom(); } return result; } - - private CodexNode[] CreateRandomNodes(int number) - { - var urls = SelectRandomUrls(number); - return codexNodeFactory.Create(urls, log, timeSet); - } - - private T PickOneRandom(List remainingItems) - { - var i = random.Next(0, remainingItems.Count); - var result = remainingItems[i]; - remainingItems.RemoveAt(i); - return result; - } } } diff --git a/ContinuousTests/Configuration.cs b/ContinuousTests/Configuration.cs index 34421ef..49aca0f 100644 --- a/ContinuousTests/Configuration.cs +++ b/ContinuousTests/Configuration.cs @@ -16,6 +16,10 @@ namespace ContinuousTests public Configuration Load() { var config = Read(); + //config.LogPath = "logs"; + //config.SleepSecondsPerTest = 10; + //config.CodexUrls = new string[] { "http://localhost:8080", "http://localhost:8081" }; + Validate(config); return config; } diff --git a/ContinuousTests/ContinuousTestRunner.cs b/ContinuousTests/ContinuousTestRunner.cs index 639390c..b1b9d44 100644 --- a/ContinuousTests/ContinuousTestRunner.cs +++ b/ContinuousTests/ContinuousTestRunner.cs @@ -13,33 +13,43 @@ namespace ContinuousTests public void Run() { var config = configLoader.Load(); - var log = new TestLog(config.LogPath, true); - - 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(""); + StartupChecks(config); 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 { - run.Run(); + result = allTestsRun.RunAll(); } catch (Exception ex) { log.Error($"Exception during test run: " + ex); } + if (result == ContinuousTestResult.Failed) + { + log.MarkAsFailed(); + } + 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) { var tests = testFactory.CreateTests(); @@ -106,4 +116,10 @@ namespace ContinuousTests return true; } } + + public enum ContinuousTestResult + { + Passed, + Failed + } } diff --git a/Logging/FixtureLog.cs b/Logging/FixtureLog.cs index 1502ec9..53eae10 100644 --- a/Logging/FixtureLog.cs +++ b/Logging/FixtureLog.cs @@ -8,19 +8,19 @@ namespace Logging private readonly string fullName; private readonly LogConfig config; - public FixtureLog(LogConfig config) + public FixtureLog(LogConfig config, string name = "") : base(config.DebugEnabled) { start = DateTime.UtcNow; var folder = DetermineFolder(config); - var fixtureName = GetFixtureName(); + var fixtureName = GetFixtureName(name); fullName = Path.Combine(folder, fixtureName); 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() @@ -36,10 +36,12 @@ namespace Logging Pad(start.Day)); } - private string GetFixtureName() + private string GetFixtureName(string name) { var test = TestContext.CurrentContext.Test; 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('.', '-')}"; } diff --git a/Logging/TestLog.cs b/Logging/TestLog.cs index 39f70a0..6ac0c99 100644 --- a/Logging/TestLog.cs +++ b/Logging/TestLog.cs @@ -9,10 +9,10 @@ namespace Logging private readonly string methodName; private readonly string fullName; - public TestLog(string folder, bool debug) + public TestLog(string folder, bool debug, string name = "") : base(debug) { - methodName = GetMethodName(); + methodName = GetMethodName(name); fullName = Path.Combine(folder, methodName); Log($"*** Begin: {methodName}"); @@ -39,13 +39,15 @@ namespace Logging MarkAsFailed(); } } + protected override LogFile CreateLogFile() { 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 args = FormatArguments(test); return $"{test.MethodName}{args}"; diff --git a/Utils/RandomUtils.cs b/Utils/RandomUtils.cs new file mode 100644 index 0000000..0cf0132 --- /dev/null +++ b/Utils/RandomUtils.cs @@ -0,0 +1,15 @@ +namespace Utils +{ + public static class RandomUtils + { + private static readonly Random random = new Random(); + + public static T PickOneRandom(this List remainingItems) + { + var i = random.Next(0, remainingItems.Count); + var result = remainingItems[i]; + remainingItems.RemoveAt(i); + return result; + } + } +}