2
0
mirror of synced 2025-01-12 01:24:23 +00:00

Setting up cancelling

This commit is contained in:
benbierens 2023-06-28 16:19:37 +02:00
parent efc638a0f9
commit eaa218f8e0
No known key found for this signature in database
GPG Key ID: FE44815D96D0A1AA
6 changed files with 97 additions and 22 deletions

View File

@ -21,12 +21,13 @@ namespace ContinuousTests
private const string UploadFailedMessage = "Unable to store block"; private const string UploadFailedMessage = "Unable to store block";
public void Initialize(CodexNode[] nodes, BaseLog log, FileManager fileManager, Configuration configuration) public void Initialize(CodexNode[] nodes, BaseLog log, FileManager fileManager, Configuration configuration, CancellationToken cancelToken)
{ {
Nodes = nodes; Nodes = nodes;
Log = log; Log = log;
FileManager = fileManager; FileManager = fileManager;
Configuration = configuration; Configuration = configuration;
CancelToken = cancelToken;
if (nodes != null) if (nodes != null)
{ {
@ -43,6 +44,7 @@ namespace ContinuousTests
public IFileManager FileManager { get; private set; } = null!; public IFileManager FileManager { get; private set; } = null!;
public Configuration Configuration { get; private set; } = null!; public Configuration Configuration { get; private set; } = null!;
public virtual ITimeSet TimeSet { get { return new DefaultTimeSet(); } } public virtual ITimeSet TimeSet { get { return new DefaultTimeSet(); } }
public CancellationToken CancelToken { get; private set; } = null;
public NodeRunner NodeRunner { get; private set; } = null!; public NodeRunner NodeRunner { get; private set; } = null!;
public abstract int RequiredNumberOfNodes { get; } public abstract int RequiredNumberOfNodes { get; }

View File

@ -10,34 +10,41 @@ namespace ContinuousTests
private readonly TestFactory testFactory = new TestFactory(); private readonly TestFactory testFactory = new TestFactory();
private readonly Configuration config; private readonly Configuration config;
private readonly StartupChecker startupChecker; private readonly StartupChecker startupChecker;
private readonly CancellationToken cancelToken;
public ContinuousTestRunner(string[] args) public ContinuousTestRunner(string[] args, CancellationToken cancelToken)
{ {
config = configLoader.Load(args); config = configLoader.Load(args);
startupChecker = new StartupChecker(config); startupChecker = new StartupChecker(config);
this.cancelToken = cancelToken;
} }
public void Run() public void Run()
{ {
startupChecker.Check(); startupChecker.Check();
var taskFactory = new TaskFactory();
var overviewLog = new FixtureLog(new LogConfig(config.LogPath, false), "Overview"); var overviewLog = new FixtureLog(new LogConfig(config.LogPath, false), "Overview");
overviewLog.Log("Continuous tests starting..."); overviewLog.Log("Continuous tests starting...");
var allTests = testFactory.CreateTests(); var allTests = testFactory.CreateTests();
ClearAllCustomNamespaces(allTests, overviewLog); ClearAllCustomNamespaces(allTests, overviewLog);
var testLoop = allTests.Select(t => new TestLoop(config, overviewLog, t.GetType(), t.RunTestEvery)).ToArray(); var testLoops = allTests.Select(t => new TestLoop(taskFactory, config, overviewLog, t.GetType(), t.RunTestEvery, cancelToken)).ToArray();
foreach (var t in testLoop) foreach (var testLoop in testLoops)
{ {
overviewLog.Log("Launching test-loop for " + t.Name); cancelToken.ThrowIfCancellationRequested();
t.Begin();
overviewLog.Log("Launching test-loop for " + testLoop.Name);
testLoop.Begin();
Thread.Sleep(TimeSpan.FromSeconds(15)); Thread.Sleep(TimeSpan.FromSeconds(15));
} }
overviewLog.Log("All test-loops launched."); overviewLog.Log("All test-loops launched.");
while (true) Thread.Sleep((2 ^ 31) - 1); cancelToken.WaitHandle.WaitOne();
overviewLog.Log("Cancelling all test-loops...");
taskFactory.WaitAll();
} }
private void ClearAllCustomNamespaces(ContinuousTest[] allTests, FixtureLog log) private void ClearAllCustomNamespaces(ContinuousTest[] allTests, FixtureLog log)

View File

@ -6,7 +6,19 @@ public class Program
{ {
Console.WriteLine("Codex Continous-Test-Runner."); Console.WriteLine("Codex Continous-Test-Runner.");
Console.WriteLine("Running..."); Console.WriteLine("Running...");
var runner = new ContinuousTestRunner(args);
var cts = new CancellationTokenSource();
var runner = new ContinuousTestRunner(args, cts.Token);
Console.CancelKeyPress += (sender, e) =>
{
Console.WriteLine("Stopping...");
e.Cancel = true;
cts.Cancel();
};
runner.Run(); runner.Run();
Console.WriteLine("Done.");
} }
} }

View File

@ -12,21 +12,24 @@ namespace ContinuousTests
{ {
private readonly CodexNodeFactory codexNodeFactory = new CodexNodeFactory(); private readonly CodexNodeFactory codexNodeFactory = new CodexNodeFactory();
private readonly List<Exception> exceptions = new List<Exception>(); private readonly List<Exception> exceptions = new List<Exception>();
private readonly TaskFactory taskFactory;
private readonly Configuration config; private readonly Configuration config;
private readonly BaseLog overviewLog; private readonly BaseLog overviewLog;
private readonly TestHandle handle; private readonly TestHandle handle;
private readonly CancellationToken cancelToken;
private readonly CodexNode[] nodes; private readonly CodexNode[] nodes;
private readonly FileManager fileManager; private readonly FileManager fileManager;
private readonly FixtureLog fixtureLog; private readonly FixtureLog fixtureLog;
private readonly string testName; private readonly string testName;
private readonly string dataFolder; private readonly string dataFolder;
public SingleTestRun(Configuration config, BaseLog overviewLog, TestHandle handle) public SingleTestRun(TaskFactory taskFactory, Configuration config, BaseLog overviewLog, TestHandle handle, CancellationToken cancelToken)
{ {
this.taskFactory = taskFactory;
this.config = config; this.config = config;
this.overviewLog = overviewLog; this.overviewLog = overviewLog;
this.handle = handle; this.handle = handle;
this.cancelToken = cancelToken;
testName = handle.Test.GetType().Name; testName = handle.Test.GetType().Name;
fixtureLog = new FixtureLog(new LogConfig(config.LogPath, false), testName); fixtureLog = new FixtureLog(new LogConfig(config.LogPath, false), testName);
@ -37,7 +40,7 @@ namespace ContinuousTests
public void Run() public void Run()
{ {
Task.Run(() => taskFactory.Run(() =>
{ {
try try
{ {
@ -75,6 +78,8 @@ namespace ContinuousTests
var t = earliestMoment; var t = earliestMoment;
while (true) while (true)
{ {
cancelToken.ThrowIfCancellationRequested();
RunMoment(t); RunMoment(t);
if (handle.Test.TestFailMode == TestFailMode.StopAfterFirstFailure && exceptions.Any()) if (handle.Test.TestFailMode == TestFailMode.StopAfterFirstFailure && exceptions.Any())
@ -86,9 +91,10 @@ namespace ContinuousTests
var nextMoment = handle.GetNextMoment(t); var nextMoment = handle.GetNextMoment(t);
if (nextMoment != null) if (nextMoment != null)
{ {
Log($" > Next TestMoment in {nextMoment.Value} seconds..."); var delta = TimeSpan.FromSeconds(nextMoment.Value - t);
t += nextMoment.Value; Log($" > Next TestMoment in {Time.FormatDuration(delta)} seconds...");
Thread.Sleep(nextMoment.Value * 1000); cancelToken.WaitHandle.WaitOne(delta);
t = nextMoment.Value;
} }
else else
{ {
@ -144,12 +150,12 @@ namespace ContinuousTests
private void InitializeTest(string name) private void InitializeTest(string name)
{ {
Log($" > Running TestMoment '{name}'"); Log($" > Running TestMoment '{name}'");
handle.Test.Initialize(nodes, fixtureLog, fileManager, config); handle.Test.Initialize(nodes, fixtureLog, fileManager, config, cancelToken);
} }
private void DecommissionTest() private void DecommissionTest()
{ {
handle.Test.Initialize(null!, null!, null!, null!); handle.Test.Initialize(null!, null!, null!, null!, cancelToken);
} }
private void Log(string msg) private void Log(string msg)

View File

@ -0,0 +1,39 @@
namespace ContinuousTests
{
public class TaskFactory
{
private readonly object taskLock = new();
private readonly List<Task> activeTasks = new List<Task>();
public void Run(Action action)
{
lock (taskLock)
{
activeTasks.Add(Task.Run(action).ContinueWith(CleanupTask, null));
}
}
public void WaitAll()
{
var tasks = activeTasks.ToArray();
Task.WaitAll(tasks);
var moreTasks = false;
lock (taskLock)
{
activeTasks.RemoveAll(task => task.IsCompleted);
moreTasks = activeTasks.Any();
}
if (moreTasks) WaitAll();
}
private void CleanupTask(Task completedTask, object? arg)
{
lock (taskLock)
{
activeTasks.Remove(completedTask);
}
}
}
}

View File

@ -4,18 +4,21 @@ namespace ContinuousTests
{ {
public class TestLoop public class TestLoop
{ {
private readonly TaskFactory taskFactory;
private readonly Configuration config; private readonly Configuration config;
private readonly BaseLog overviewLog; private readonly BaseLog overviewLog;
private readonly Type testType; private readonly Type testType;
private readonly TimeSpan runsEvery; private readonly TimeSpan runsEvery;
private readonly CancellationToken cancelToken;
public TestLoop(Configuration config, BaseLog overviewLog, Type testType, TimeSpan runsEvery) public TestLoop(TaskFactory taskFactory, Configuration config, BaseLog overviewLog, Type testType, TimeSpan runsEvery, CancellationToken cancelToken)
{ {
this.taskFactory = taskFactory;
this.config = config; this.config = config;
this.overviewLog = overviewLog; this.overviewLog = overviewLog;
this.testType = testType; this.testType = testType;
this.runsEvery = runsEvery; this.runsEvery = runsEvery;
this.cancelToken = cancelToken;
Name = testType.Name; Name = testType.Name;
} }
@ -23,17 +26,23 @@ namespace ContinuousTests
public void Begin() public void Begin()
{ {
Task.Run(() => taskFactory.Run(() =>
{ {
try try
{ {
while (true) while (true)
{ {
cancelToken.ThrowIfCancellationRequested();
StartTest(); StartTest();
Thread.Sleep(runsEvery);
cancelToken.WaitHandle.WaitOne(runsEvery);
} }
} }
catch(Exception ex) catch (OperationCanceledException)
{
overviewLog.Log("Test-loop " + testType.Name + " is cancelled.");
}
catch (Exception ex)
{ {
overviewLog.Error("Test infra failure: TestLoop failed with " + ex); overviewLog.Error("Test infra failure: TestLoop failed with " + ex);
Environment.Exit(-1); Environment.Exit(-1);
@ -45,7 +54,7 @@ namespace ContinuousTests
{ {
var test = (ContinuousTest)Activator.CreateInstance(testType)!; var test = (ContinuousTest)Activator.CreateInstance(testType)!;
var handle = new TestHandle(test); var handle = new TestHandle(test);
var run = new SingleTestRun(config, overviewLog, handle); var run = new SingleTestRun(taskFactory, config, overviewLog, handle, cancelToken);
run.Run(); run.Run();
} }
} }