2023-06-21 09:01:48 +00:00
|
|
|
|
using DistTestCore.Codex;
|
|
|
|
|
using DistTestCore;
|
|
|
|
|
using Logging;
|
|
|
|
|
using Utils;
|
2023-06-23 08:14:16 +00:00
|
|
|
|
using KubernetesWorkflow;
|
2023-06-21 09:01:48 +00:00
|
|
|
|
|
|
|
|
|
namespace ContinuousTests
|
|
|
|
|
{
|
|
|
|
|
public class SingleTestRun
|
|
|
|
|
{
|
|
|
|
|
private readonly CodexNodeFactory codexNodeFactory = new CodexNodeFactory();
|
2023-06-25 07:53:10 +00:00
|
|
|
|
private readonly List<Exception> exceptions = new List<Exception>();
|
2023-06-21 09:01:48 +00:00
|
|
|
|
private readonly Configuration config;
|
2023-06-25 07:53:10 +00:00
|
|
|
|
private readonly TestHandle handle;
|
2023-06-21 09:01:48 +00:00
|
|
|
|
private readonly CodexNode[] nodes;
|
|
|
|
|
private readonly FileManager fileManager;
|
2023-06-25 07:53:10 +00:00
|
|
|
|
private readonly FixtureLog fixtureLog;
|
2023-06-25 08:50:01 +00:00
|
|
|
|
private readonly string dataFolder;
|
2023-06-21 09:01:48 +00:00
|
|
|
|
|
2023-06-25 07:53:10 +00:00
|
|
|
|
public SingleTestRun(Configuration config, TestHandle handle)
|
2023-06-21 09:01:48 +00:00
|
|
|
|
{
|
|
|
|
|
this.config = config;
|
2023-06-25 07:53:10 +00:00
|
|
|
|
this.handle = handle;
|
2023-06-21 09:01:48 +00:00
|
|
|
|
|
2023-06-25 07:53:10 +00:00
|
|
|
|
var testName = handle.Test.GetType().Name;
|
|
|
|
|
fixtureLog = new FixtureLog(new LogConfig(config.LogPath, false), testName);
|
2023-06-21 09:01:48 +00:00
|
|
|
|
|
2023-06-25 07:53:10 +00:00
|
|
|
|
nodes = CreateRandomNodes(handle.Test.RequiredNumberOfNodes);
|
2023-06-25 08:50:01 +00:00
|
|
|
|
dataFolder = config.DataPath + "-" + Guid.NewGuid();
|
2023-06-25 07:53:10 +00:00
|
|
|
|
fileManager = new FileManager(fixtureLog, CreateFileManagerConfiguration());
|
2023-06-21 09:01:48 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void Run()
|
|
|
|
|
{
|
2023-06-25 07:53:10 +00:00
|
|
|
|
Task.Run(() =>
|
|
|
|
|
{
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
RunTest();
|
|
|
|
|
|
|
|
|
|
if (!config.KeepPassedTestLogs) fixtureLog.Delete();
|
|
|
|
|
}
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
{
|
|
|
|
|
fixtureLog.Error("Test run failed with exception: " + ex);
|
|
|
|
|
fixtureLog.MarkAsFailed();
|
|
|
|
|
}
|
|
|
|
|
fileManager.DeleteAllTestFiles();
|
2023-06-25 08:50:01 +00:00
|
|
|
|
Directory.Delete(dataFolder, true);
|
2023-06-25 07:53:10 +00:00
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void RunTest()
|
|
|
|
|
{
|
|
|
|
|
var earliestMoment = handle.GetEarliestMoment();
|
|
|
|
|
|
|
|
|
|
var t = earliestMoment;
|
2023-06-25 08:50:01 +00:00
|
|
|
|
while (true)
|
2023-06-25 07:53:10 +00:00
|
|
|
|
{
|
|
|
|
|
RunMoment(t);
|
|
|
|
|
|
|
|
|
|
if (handle.Test.TestFailMode == TestFailMode.StopAfterFirstFailure && exceptions.Any())
|
|
|
|
|
{
|
|
|
|
|
Log("Exception detected. TestFailMode = StopAfterFirstFailure. Stopping...");
|
|
|
|
|
throw exceptions.Single();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var nextMoment = handle.GetNextMoment(t);
|
|
|
|
|
if (nextMoment != null)
|
|
|
|
|
{
|
|
|
|
|
Log($" > Next TestMoment in {nextMoment.Value} seconds...");
|
|
|
|
|
t += nextMoment.Value;
|
|
|
|
|
Thread.Sleep(nextMoment.Value * 1000);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2023-06-25 08:50:01 +00:00
|
|
|
|
if (exceptions.Any())
|
|
|
|
|
{
|
|
|
|
|
Log(" > Completed last test moment. Test failed.");
|
|
|
|
|
throw exceptions.First();
|
|
|
|
|
}
|
|
|
|
|
Log(" > Completed last test moment. Test passed.");
|
|
|
|
|
return;
|
2023-06-25 07:53:10 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void RunMoment(int t)
|
|
|
|
|
{
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
handle.InvokeMoment(t, InitializeTest);
|
|
|
|
|
}
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
{
|
|
|
|
|
Log($" > TestMoment yielded exception: " + ex);
|
|
|
|
|
exceptions.Add(ex);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
DecommissionTest();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void InitializeTest(string name)
|
|
|
|
|
{
|
|
|
|
|
Log($" > Running TestMoment '{name}'");
|
|
|
|
|
handle.Test.Initialize(nodes, fixtureLog, fileManager);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void DecommissionTest()
|
|
|
|
|
{
|
|
|
|
|
handle.Test.Initialize(null!, null!, null!);
|
2023-06-21 09:01:48 +00:00
|
|
|
|
}
|
|
|
|
|
|
2023-06-25 07:53:10 +00:00
|
|
|
|
private void Log(string msg)
|
2023-06-21 09:01:48 +00:00
|
|
|
|
{
|
2023-06-25 07:53:10 +00:00
|
|
|
|
fixtureLog.Log(msg);
|
2023-06-21 09:01:48 +00:00
|
|
|
|
}
|
|
|
|
|
|
2023-06-25 07:53:10 +00:00
|
|
|
|
private CodexNode[] CreateRandomNodes(int number)
|
2023-06-21 09:01:48 +00:00
|
|
|
|
{
|
2023-06-23 08:14:16 +00:00
|
|
|
|
var containers = SelectRandomContainers(number);
|
2023-06-25 07:53:10 +00:00
|
|
|
|
fixtureLog.Log("Selected nodes: " + string.Join(",", containers.Select(c => c.Name)));
|
|
|
|
|
return codexNodeFactory.Create(containers, fixtureLog, handle.Test.TimeSet);
|
2023-06-21 09:01:48 +00:00
|
|
|
|
}
|
|
|
|
|
|
2023-06-23 08:14:16 +00:00
|
|
|
|
private RunningContainer[] SelectRandomContainers(int number)
|
2023-06-21 09:01:48 +00:00
|
|
|
|
{
|
2023-06-23 08:14:16 +00:00
|
|
|
|
var containers = config.CodexDeployment.CodexContainers.ToList();
|
|
|
|
|
var result = new RunningContainer[number];
|
2023-06-21 09:01:48 +00:00
|
|
|
|
for (var i = 0; i < number; i++)
|
|
|
|
|
{
|
2023-06-23 08:14:16 +00:00
|
|
|
|
result[i] = containers.PickOneRandom();
|
2023-06-21 09:01:48 +00:00
|
|
|
|
}
|
|
|
|
|
return result;
|
|
|
|
|
}
|
2023-06-25 07:53:10 +00:00
|
|
|
|
|
|
|
|
|
private DistTestCore.Configuration CreateFileManagerConfiguration()
|
|
|
|
|
{
|
2023-06-25 08:50:01 +00:00
|
|
|
|
return new DistTestCore.Configuration(null, string.Empty, false, dataFolder,
|
2023-06-25 07:53:10 +00:00
|
|
|
|
CodexLogLevel.Error, TestRunnerLocation.ExternalToCluster);
|
|
|
|
|
}
|
2023-06-21 09:01:48 +00:00
|
|
|
|
}
|
|
|
|
|
}
|