Instantiate node-handles for each individual test. Allows for time-set selection.
This commit is contained in:
parent
d23f5aa29d
commit
978d2d3a84
|
@ -0,0 +1,22 @@
|
||||||
|
using DistTestCore;
|
||||||
|
using DistTestCore.Codex;
|
||||||
|
using Logging;
|
||||||
|
using Utils;
|
||||||
|
|
||||||
|
namespace ContinuousTests
|
||||||
|
{
|
||||||
|
public class CodexNodeFactory
|
||||||
|
{
|
||||||
|
public CodexNode[] Create(string[] urls, BaseLog log, ITimeSet timeSet)
|
||||||
|
{
|
||||||
|
return urls.Select(url =>
|
||||||
|
{
|
||||||
|
var cutIndex = url.LastIndexOf(':');
|
||||||
|
var host = url.Substring(0, cutIndex);
|
||||||
|
var port = url.Substring(cutIndex + 1);
|
||||||
|
var address = new Address(host, Convert.ToInt32(port));
|
||||||
|
return new CodexNode(log, timeSet, address);
|
||||||
|
}).ToArray();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -40,7 +40,7 @@ namespace ContinuousTests
|
||||||
if (!string.IsNullOrEmpty(logPath) && !string.IsNullOrEmpty(codexUrls) && !string.IsNullOrEmpty(sleep))
|
if (!string.IsNullOrEmpty(logPath) && !string.IsNullOrEmpty(codexUrls) && !string.IsNullOrEmpty(sleep))
|
||||||
{
|
{
|
||||||
var urls = codexUrls.Split(';', StringSplitOptions.RemoveEmptyEntries);
|
var urls = codexUrls.Split(';', StringSplitOptions.RemoveEmptyEntries);
|
||||||
var ms = 0;
|
int ms;
|
||||||
if (int.TryParse(sleep, out ms))
|
if (int.TryParse(sleep, out ms))
|
||||||
{
|
{
|
||||||
if (urls.Length > 0)
|
if (urls.Length > 0)
|
||||||
|
|
|
@ -0,0 +1,82 @@
|
||||||
|
using DistTestCore;
|
||||||
|
using DistTestCore.Codex;
|
||||||
|
using Logging;
|
||||||
|
|
||||||
|
namespace ContinuousTests
|
||||||
|
{
|
||||||
|
public abstract class ContinuousTestLongTimeouts : ContinuousTest
|
||||||
|
{
|
||||||
|
public override ITimeSet TimeSet => new LongTimeSet();
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract class ContinuousTest
|
||||||
|
{
|
||||||
|
private const string UploadFailedMessage = "Unable to store block";
|
||||||
|
|
||||||
|
public void Initialize(CodexNode[] nodes, BaseLog log, FileManager fileManager)
|
||||||
|
{
|
||||||
|
Nodes = nodes;
|
||||||
|
Log = log;
|
||||||
|
FileManager = fileManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
public CodexNode[] Nodes { get; private set; } = null!;
|
||||||
|
public BaseLog Log { get; private set; } = null!;
|
||||||
|
public IFileManager FileManager { get; private set; } = null!;
|
||||||
|
public virtual ITimeSet TimeSet { get { return new DefaultTimeSet(); } }
|
||||||
|
|
||||||
|
public abstract int RequiredNumberOfNodes { get; }
|
||||||
|
|
||||||
|
public string Name
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return GetType().Name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract void Run();
|
||||||
|
|
||||||
|
public ContentId? UploadFile(CodexNode node, TestFile file)
|
||||||
|
{
|
||||||
|
using var fileStream = File.OpenRead(file.Filename);
|
||||||
|
|
||||||
|
var logMessage = $"Uploading file {file.Describe()}...";
|
||||||
|
var response = Stopwatch.Measure(Log, logMessage, () =>
|
||||||
|
{
|
||||||
|
return node.UploadFile(fileStream);
|
||||||
|
});
|
||||||
|
|
||||||
|
if (response.StartsWith(UploadFailedMessage))
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
Log.Log($"Uploaded file. Received contentId: '{response}'.");
|
||||||
|
return new ContentId(response);
|
||||||
|
}
|
||||||
|
|
||||||
|
public TestFile DownloadContent(CodexNode node, ContentId contentId, string fileLabel = "")
|
||||||
|
{
|
||||||
|
var logMessage = $"Downloading for contentId: '{contentId.Id}'...";
|
||||||
|
var file = FileManager.CreateEmptyTestFile(fileLabel);
|
||||||
|
Stopwatch.Measure(Log, logMessage, () => DownloadToFile(node, contentId.Id, file));
|
||||||
|
Log.Log($"Downloaded file {file.Describe()} to '{file.Filename}'.");
|
||||||
|
return file;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void DownloadToFile(CodexNode node, string contentId, TestFile file)
|
||||||
|
{
|
||||||
|
using var fileStream = File.OpenWrite(file.Filename);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
using var downloadStream = node.DownloadFile(contentId);
|
||||||
|
downloadStream.CopyTo(fileStream);
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
Log.Log($"Failed to download file '{contentId}'.");
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,14 +1,14 @@
|
||||||
using DistTestCore;
|
using DistTestCore;
|
||||||
using DistTestCore.Codex;
|
using DistTestCore.Codex;
|
||||||
using Logging;
|
using Logging;
|
||||||
using Utils;
|
|
||||||
|
|
||||||
namespace ContinuousTests
|
namespace ContinuousTests
|
||||||
{
|
{
|
||||||
public class ContinuousTestRunner
|
public class ContinuousTestRunner
|
||||||
{
|
{
|
||||||
private readonly ConfigLoader configLoader = new ConfigLoader();
|
private readonly ConfigLoader configLoader = new ConfigLoader();
|
||||||
private readonly TestFinder testFinder = new TestFinder();
|
private readonly TestFactory testFactory = new TestFactory();
|
||||||
|
private readonly CodexNodeFactory codexNodeFactory = new CodexNodeFactory();
|
||||||
|
|
||||||
public void Run()
|
public void Run()
|
||||||
{
|
{
|
||||||
|
@ -19,13 +19,13 @@ namespace ContinuousTests
|
||||||
log.Log("Checking configuration...");
|
log.Log("Checking configuration...");
|
||||||
PreflightCheck(config);
|
PreflightCheck(config);
|
||||||
log.Log("Contacting Codex nodes...");
|
log.Log("Contacting Codex nodes...");
|
||||||
var nodes = CreateCodexNodes(log, new LongTimeSet(), config);
|
CheckCodexNodes(log, config);
|
||||||
log.Log("OK");
|
log.Log("All OK.");
|
||||||
log.Log("");
|
log.Log("");
|
||||||
|
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
var run = new TestRun(config, log, testFinder, nodes);
|
var run = new TestRun(config, log, testFactory);
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
@ -42,7 +42,7 @@ namespace ContinuousTests
|
||||||
|
|
||||||
private void PreflightCheck(Configuration config)
|
private void PreflightCheck(Configuration config)
|
||||||
{
|
{
|
||||||
var tests = testFinder.GetTests();
|
var tests = testFactory.CreateTests();
|
||||||
if (!tests.Any())
|
if (!tests.Any())
|
||||||
{
|
{
|
||||||
throw new Exception("Unable to find any tests.");
|
throw new Exception("Unable to find any tests.");
|
||||||
|
@ -57,20 +57,20 @@ namespace ContinuousTests
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!Directory.Exists(config.LogPath))
|
||||||
|
{
|
||||||
|
Directory.CreateDirectory(config.LogPath);
|
||||||
|
}
|
||||||
|
|
||||||
if (errors.Any())
|
if (errors.Any())
|
||||||
{
|
{
|
||||||
throw new Exception("Prerun check failed: " + string.Join(", ", errors));
|
throw new Exception("Prerun check failed: " + string.Join(", ", errors));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private CodexNode[] CreateCodexNodes(BaseLog log, ITimeSet timeSet, Configuration config)
|
private void CheckCodexNodes(BaseLog log, Configuration config)
|
||||||
{
|
{
|
||||||
var nodes = config.CodexUrls.Select(url =>
|
var nodes = codexNodeFactory.Create(config.CodexUrls, log, new DefaultTimeSet());
|
||||||
{
|
|
||||||
var address = new Address(url, 1234);
|
|
||||||
return new CodexNode(log, timeSet, address);
|
|
||||||
}).ToArray();
|
|
||||||
|
|
||||||
var pass = true;
|
var pass = true;
|
||||||
foreach (var n in nodes)
|
foreach (var n in nodes)
|
||||||
{
|
{
|
||||||
|
@ -90,8 +90,6 @@ namespace ContinuousTests
|
||||||
{
|
{
|
||||||
throw new Exception("Not all codex nodes responded.");
|
throw new Exception("Not all codex nodes responded.");
|
||||||
}
|
}
|
||||||
|
|
||||||
return nodes;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool EnsureOnline(CodexNode n)
|
private bool EnsureOnline(CodexNode n)
|
||||||
|
|
|
@ -1,33 +0,0 @@
|
||||||
using DistTestCore;
|
|
||||||
using DistTestCore.Codex;
|
|
||||||
using Logging;
|
|
||||||
|
|
||||||
namespace ContinuousTests
|
|
||||||
{
|
|
||||||
public interface IContinuousTest
|
|
||||||
{
|
|
||||||
string Name { get; }
|
|
||||||
int RequiredNumberOfNodes { get; }
|
|
||||||
|
|
||||||
void Run();
|
|
||||||
}
|
|
||||||
|
|
||||||
public abstract class ContinuousTest : IContinuousTest
|
|
||||||
{
|
|
||||||
public CodexNode[] Nodes { get; set; } = null!;
|
|
||||||
public BaseLog Log { get; set; } = null!;
|
|
||||||
public FileManager FileManager { get; set; } = null!;
|
|
||||||
|
|
||||||
public abstract int RequiredNumberOfNodes { get; }
|
|
||||||
|
|
||||||
public string Name
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return GetType().Name;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public abstract void Run();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,12 @@
|
||||||
|
namespace ContinuousTests
|
||||||
|
{
|
||||||
|
public class TestFactory
|
||||||
|
{
|
||||||
|
public ContinuousTest[] CreateTests()
|
||||||
|
{
|
||||||
|
var types = GetType().Assembly.GetTypes();
|
||||||
|
var testTypes = types.Where(t => typeof(ContinuousTest).IsAssignableFrom(t) && !t.IsAbstract);
|
||||||
|
return testTypes.Select(t => (ContinuousTest)Activator.CreateInstance(t)!).ToArray();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,24 +0,0 @@
|
||||||
namespace ContinuousTests
|
|
||||||
{
|
|
||||||
public class TestFinder
|
|
||||||
{
|
|
||||||
private readonly List<IContinuousTest> testList = new List<IContinuousTest>();
|
|
||||||
|
|
||||||
public IContinuousTest[] GetTests()
|
|
||||||
{
|
|
||||||
if (!testList.Any()) FindTests();
|
|
||||||
return testList.ToArray();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void FindTests()
|
|
||||||
{
|
|
||||||
var types = GetType().Assembly.GetTypes();
|
|
||||||
var testTypes = types.Where(t => typeof(IContinuousTest).IsAssignableFrom(t) && !t.IsAbstract);
|
|
||||||
foreach (var testType in testTypes)
|
|
||||||
{
|
|
||||||
var t = Activator.CreateInstance(testType);
|
|
||||||
testList.Add((IContinuousTest)t!);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -7,29 +7,30 @@ namespace ContinuousTests
|
||||||
public class TestRun
|
public class TestRun
|
||||||
{
|
{
|
||||||
private readonly Random random = new Random();
|
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 BaseLog log;
|
||||||
private readonly TestFinder testFinder;
|
private readonly TestFactory testFinder;
|
||||||
private readonly CodexNode[] nodes;
|
|
||||||
private readonly FileManager fileManager;
|
private readonly FileManager fileManager;
|
||||||
|
private ITimeSet timeSet;
|
||||||
|
|
||||||
public TestRun(Configuration config, BaseLog log, TestFinder testFinder, CodexNode[] nodes)
|
public TestRun(Configuration config, BaseLog log, TestFactory testFinder)
|
||||||
{
|
{
|
||||||
this.config = config;
|
this.config = config;
|
||||||
this.log = log;
|
this.log = log;
|
||||||
this.testFinder = testFinder;
|
this.testFinder = testFinder;
|
||||||
this.nodes = nodes;
|
|
||||||
fileManager = new FileManager(log, new DistTestCore.Configuration());
|
fileManager = new FileManager(log, new DistTestCore.Configuration());
|
||||||
|
timeSet = new DefaultTimeSet();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Run()
|
public void Run()
|
||||||
{
|
{
|
||||||
var remainingTests = testFinder.GetTests().ToList();
|
var remainingTests = testFinder.CreateTests().ToList();
|
||||||
while (remainingTests.Any())
|
while (remainingTests.Any())
|
||||||
{
|
{
|
||||||
var test = PickOneRandom(remainingTests);
|
var test = PickOneRandom(remainingTests);
|
||||||
var selectedNodes = SelectRandomNodes(test.RequiredNumberOfNodes);
|
var nodes = CreateRandomNodes(test.RequiredNumberOfNodes);
|
||||||
AssignEssentials(test, selectedNodes);
|
AssignEssentials(test, nodes);
|
||||||
fileManager.PushFileSet();
|
fileManager.PushFileSet();
|
||||||
|
|
||||||
log.Log($"Start '{test.Name}'");
|
log.Log($"Start '{test.Name}'");
|
||||||
|
@ -49,33 +50,34 @@ namespace ContinuousTests
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void AssignEssentials(IContinuousTest test, CodexNode[] nodes)
|
private void AssignEssentials(ContinuousTest test, CodexNode[] nodes)
|
||||||
{
|
{
|
||||||
var t = (ContinuousTest)test;
|
test.Initialize(nodes, log, fileManager);
|
||||||
t.Nodes = nodes;
|
|
||||||
t.Log = log;
|
|
||||||
t.FileManager = fileManager;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ClearEssentials(IContinuousTest test)
|
private void ClearEssentials(ContinuousTest test)
|
||||||
{
|
{
|
||||||
var t = (ContinuousTest)test;
|
// Looks a little strange, but prevents finished test from interacting further.
|
||||||
t.Nodes = null!;
|
test.Initialize(null!, null!, null!);
|
||||||
t.Log = null!;
|
|
||||||
t.FileManager = null!;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private CodexNode[] SelectRandomNodes(int number)
|
private string[] SelectRandomUrls(int number)
|
||||||
{
|
{
|
||||||
var remainingNodes = nodes.ToList();
|
var urls = config.CodexUrls.ToList();
|
||||||
var result = new CodexNode[number];
|
var result = new string[number];
|
||||||
for (var i = 0; i < number; i++)
|
for (var i = 0; i < number; i++)
|
||||||
{
|
{
|
||||||
result[i] = PickOneRandom(remainingNodes);
|
result[i] = PickOneRandom(urls);
|
||||||
}
|
}
|
||||||
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)
|
private T PickOneRandom<T>(List<T> remainingItems)
|
||||||
{
|
{
|
||||||
var i = random.Next(0, remainingItems.Count);
|
var i = random.Next(0, remainingItems.Count);
|
||||||
|
|
|
@ -0,0 +1,22 @@
|
||||||
|
using DistTestCore;
|
||||||
|
using NUnit.Framework;
|
||||||
|
|
||||||
|
namespace ContinuousTests.Tests
|
||||||
|
{
|
||||||
|
public class TwoClientTest : ContinuousTest
|
||||||
|
{
|
||||||
|
public override int RequiredNumberOfNodes => 2;
|
||||||
|
|
||||||
|
public override void Run()
|
||||||
|
{
|
||||||
|
var file = FileManager.GenerateTestFile(10.MB());
|
||||||
|
|
||||||
|
var cid = UploadFile(Nodes[0], file);
|
||||||
|
Assert.That(cid, Is.Not.Null);
|
||||||
|
|
||||||
|
var dl = DownloadContent(Nodes[1], cid!);
|
||||||
|
|
||||||
|
dl.AssertIsEqual(file);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue