Merge branch 'feature/continuous-peer-test'
This commit is contained in:
commit
a528c0111d
|
@ -28,6 +28,7 @@ namespace CodexNetDeployer
|
||||||
var workflowStartup = new StartupConfig();
|
var workflowStartup = new StartupConfig();
|
||||||
workflowStartup.Add(gethResult);
|
workflowStartup.Add(gethResult);
|
||||||
workflowStartup.Add(CreateCodexStartupConfig(bootstrapSpr, i, validatorsLeft));
|
workflowStartup.Add(CreateCodexStartupConfig(bootstrapSpr, i, validatorsLeft));
|
||||||
|
workflowStartup.NameOverride = GetCodexContainerName(i);
|
||||||
|
|
||||||
var containers = workflow.Start(1, Location.Unspecified, new CodexContainerRecipe(), workflowStartup);
|
var containers = workflow.Start(1, Location.Unspecified, new CodexContainerRecipe(), workflowStartup);
|
||||||
|
|
||||||
|
@ -75,6 +76,12 @@ namespace CodexNetDeployer
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private string GetCodexContainerName(int i)
|
||||||
|
{
|
||||||
|
if (i == 0) return "BOOTSTRAP";
|
||||||
|
return "CODEX" + i;
|
||||||
|
}
|
||||||
|
|
||||||
private CodexStartupConfig CreateCodexStartupConfig(string bootstrapSpr, int i, int validatorsLeft)
|
private CodexStartupConfig CreateCodexStartupConfig(string bootstrapSpr, int i, int validatorsLeft)
|
||||||
{
|
{
|
||||||
var codexStart = new CodexStartupConfig(config.CodexLogLevel);
|
var codexStart = new CodexStartupConfig(config.CodexLogLevel);
|
||||||
|
|
|
@ -22,8 +22,8 @@ namespace ContinuousTests
|
||||||
[Uniform("kube-config", "kc", "KUBECONFIG", true, "Path to Kubeconfig file. Use 'null' (default) to use local cluster.")]
|
[Uniform("kube-config", "kc", "KUBECONFIG", true, "Path to Kubeconfig file. Use 'null' (default) to use local cluster.")]
|
||||||
public string KubeConfigFile { get; set; } = "null";
|
public string KubeConfigFile { get; set; } = "null";
|
||||||
|
|
||||||
[Uniform("stop", "s", "STOPONFAIL", false, "If true, runner will stop on first test failure and download all cluster container logs. False by default.")]
|
[Uniform("stop", "s", "STOPONFAIL", false, "If greater than zero, runner will stop after this many test failures and download all cluster container logs. 0 by default.")]
|
||||||
public bool StopOnFailure { get; set; } = false;
|
public int StopOnFailure { get; set; } = 0;
|
||||||
|
|
||||||
[Uniform("dl-logs", "dl", "DLLOGS", false, "If true, runner will periodically download and save/append container logs to the log path.")]
|
[Uniform("dl-logs", "dl", "DLLOGS", false, "If true, runner will periodically download and save/append container logs to the log path.")]
|
||||||
public bool DownloadContainerLogs { get; set; } = false;
|
public bool DownloadContainerLogs { get; set; } = false;
|
||||||
|
|
|
@ -30,7 +30,7 @@ namespace ContinuousTests
|
||||||
|
|
||||||
ClearAllCustomNamespaces(allTests, overviewLog);
|
ClearAllCustomNamespaces(allTests, overviewLog);
|
||||||
|
|
||||||
var testLoops = allTests.Select(t => new TestLoop(taskFactory, config, overviewLog, t.GetType(), t.RunTestEvery, cancelToken)).ToArray();
|
var testLoops = allTests.Select(t => new TestLoop(taskFactory, config, overviewLog, t.GetType(), t.RunTestEvery, startupChecker, cancelToken)).ToArray();
|
||||||
|
|
||||||
foreach (var testLoop in testLoops)
|
foreach (var testLoop in testLoops)
|
||||||
{
|
{
|
||||||
|
|
|
@ -23,8 +23,9 @@ namespace ContinuousTests
|
||||||
private readonly FixtureLog fixtureLog;
|
private readonly FixtureLog fixtureLog;
|
||||||
private readonly string testName;
|
private readonly string testName;
|
||||||
private readonly string dataFolder;
|
private readonly string dataFolder;
|
||||||
|
private static int failureCount = 0;
|
||||||
|
|
||||||
public SingleTestRun(TaskFactory taskFactory, Configuration config, BaseLog overviewLog, TestHandle handle, CancellationToken cancelToken)
|
public SingleTestRun(TaskFactory taskFactory, Configuration config, BaseLog overviewLog, TestHandle handle, StartupChecker startupChecker, CancellationToken cancelToken)
|
||||||
{
|
{
|
||||||
this.taskFactory = taskFactory;
|
this.taskFactory = taskFactory;
|
||||||
this.config = config;
|
this.config = config;
|
||||||
|
@ -33,8 +34,9 @@ namespace ContinuousTests
|
||||||
this.cancelToken = cancelToken;
|
this.cancelToken = cancelToken;
|
||||||
testName = handle.Test.GetType().Name;
|
testName = handle.Test.GetType().Name;
|
||||||
fixtureLog = new FixtureLog(new LogConfig(config.LogPath, true), DateTime.UtcNow, testName);
|
fixtureLog = new FixtureLog(new LogConfig(config.LogPath, true), DateTime.UtcNow, testName);
|
||||||
|
ApplyLogReplacements(fixtureLog, startupChecker);
|
||||||
|
|
||||||
nodes = CreateRandomNodes(handle.Test.RequiredNumberOfNodes);
|
nodes = CreateRandomNodes();
|
||||||
dataFolder = config.DataPath + "-" + Guid.NewGuid();
|
dataFolder = config.DataPath + "-" + Guid.NewGuid();
|
||||||
fileManager = new FileManager(fixtureLog, CreateFileManagerConfiguration());
|
fileManager = new FileManager(fixtureLog, CreateFileManagerConfiguration());
|
||||||
}
|
}
|
||||||
|
@ -71,16 +73,26 @@ namespace ContinuousTests
|
||||||
fixtureLog.Error("Test run failed with exception: " + ex);
|
fixtureLog.Error("Test run failed with exception: " + ex);
|
||||||
fixtureLog.MarkAsFailed();
|
fixtureLog.MarkAsFailed();
|
||||||
|
|
||||||
if (config.StopOnFailure)
|
failureCount++;
|
||||||
|
if (config.StopOnFailure > 0)
|
||||||
{
|
{
|
||||||
OverviewLog("Configured to stop on first failure. Downloading cluster logs...");
|
OverviewLog($"Failures: {failureCount} / {config.StopOnFailure}");
|
||||||
DownloadClusterLogs();
|
if (failureCount >= config.StopOnFailure)
|
||||||
OverviewLog("Log download finished. Cancelling test runner...");
|
{
|
||||||
Cancellation.Cts.Cancel();
|
OverviewLog($"Configured to stop after {config.StopOnFailure} failures. Downloading cluster logs...");
|
||||||
|
DownloadClusterLogs();
|
||||||
|
OverviewLog("Log download finished. Cancelling test runner...");
|
||||||
|
Cancellation.Cts.Cancel();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void ApplyLogReplacements(FixtureLog fixtureLog, StartupChecker startupChecker)
|
||||||
|
{
|
||||||
|
foreach (var replacement in startupChecker.LogReplacements) fixtureLog.AddStringReplace(replacement.From, replacement.To);
|
||||||
|
}
|
||||||
|
|
||||||
private void RunTestMoments()
|
private void RunTestMoments()
|
||||||
{
|
{
|
||||||
var earliestMoment = handle.GetEarliestMoment();
|
var earliestMoment = handle.GetEarliestMoment();
|
||||||
|
@ -112,7 +124,7 @@ namespace ContinuousTests
|
||||||
{
|
{
|
||||||
ThrowFailTest();
|
ThrowFailTest();
|
||||||
}
|
}
|
||||||
OverviewLog(" > Test passed. " + FuturesInfo());
|
OverviewLog(" > Test passed.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -120,25 +132,19 @@ namespace ContinuousTests
|
||||||
|
|
||||||
private void ThrowFailTest()
|
private void ThrowFailTest()
|
||||||
{
|
{
|
||||||
var ex = UnpackException(exceptions.First());
|
var exs = UnpackExceptions(exceptions);
|
||||||
Log(ex.ToString());
|
var exceptionsMessage = GetCombinedExceptionsMessage(exs);
|
||||||
OverviewLog($" > Test failed {FuturesInfo()}: " + ex.Message);
|
Log(exceptionsMessage);
|
||||||
throw ex;
|
OverviewLog($" > Test failed: " + exceptionsMessage);
|
||||||
}
|
throw new Exception(exceptionsMessage);
|
||||||
|
|
||||||
private string FuturesInfo()
|
|
||||||
{
|
|
||||||
var containers = config.CodexDeployment.CodexContainers;
|
|
||||||
var nodes = codexNodeFactory.Create(config, containers, fixtureLog, handle.Test.TimeSet);
|
|
||||||
var f = nodes.Select(n => n.GetDebugFutures().ToString());
|
|
||||||
var msg = $"(Futures: [{string.Join(", ", f)}])";
|
|
||||||
return msg;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void DownloadClusterLogs()
|
private void DownloadClusterLogs()
|
||||||
{
|
{
|
||||||
var k8sFactory = new K8sFactory();
|
var k8sFactory = new K8sFactory();
|
||||||
var lifecycle = k8sFactory.CreateTestLifecycle(config.KubeConfigFile, config.LogPath, "dataPath", config.CodexDeployment.Metadata.KubeNamespace, new DefaultTimeSet(), new NullLog());
|
var log = new NullLog();
|
||||||
|
log.FullFilename = Path.Combine(config.LogPath, "NODE");
|
||||||
|
var lifecycle = k8sFactory.CreateTestLifecycle(config.KubeConfigFile, config.LogPath, "dataPath", config.CodexDeployment.Metadata.KubeNamespace, new DefaultTimeSet(), log);
|
||||||
|
|
||||||
foreach (var container in config.CodexDeployment.CodexContainers)
|
foreach (var container in config.CodexDeployment.CodexContainers)
|
||||||
{
|
{
|
||||||
|
@ -146,6 +152,16 @@ namespace ContinuousTests
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private string GetCombinedExceptionsMessage(Exception[] exceptions)
|
||||||
|
{
|
||||||
|
return string.Join(Environment.NewLine, exceptions.Select(ex => ex.ToString()));
|
||||||
|
}
|
||||||
|
|
||||||
|
private Exception[] UnpackExceptions(List<Exception> exceptions)
|
||||||
|
{
|
||||||
|
return exceptions.Select(UnpackException).ToArray();
|
||||||
|
}
|
||||||
|
|
||||||
private Exception UnpackException(Exception exception)
|
private Exception UnpackException(Exception exception)
|
||||||
{
|
{
|
||||||
if (exception is AggregateException a)
|
if (exception is AggregateException a)
|
||||||
|
@ -196,19 +212,26 @@ namespace ContinuousTests
|
||||||
private void OverviewLog(string msg)
|
private void OverviewLog(string msg)
|
||||||
{
|
{
|
||||||
Log(msg);
|
Log(msg);
|
||||||
var containerNames = $"({string.Join(",", nodes.Select(n => n.Container.Name))})";
|
var containerNames = GetContainerNames();
|
||||||
overviewLog.Log($"{containerNames} {testName}: {msg}");
|
overviewLog.Log($"{containerNames} {testName}: {msg}");
|
||||||
}
|
}
|
||||||
|
|
||||||
private CodexAccess[] CreateRandomNodes(int number)
|
private string GetContainerNames()
|
||||||
{
|
{
|
||||||
var containers = SelectRandomContainers(number);
|
if (handle.Test.RequiredNumberOfNodes == -1) return "(All Nodes)";
|
||||||
|
return $"({string.Join(",", nodes.Select(n => n.Container.Name))})";
|
||||||
|
}
|
||||||
|
|
||||||
|
private CodexAccess[] CreateRandomNodes()
|
||||||
|
{
|
||||||
|
var containers = SelectRandomContainers();
|
||||||
fixtureLog.Log("Selected nodes: " + string.Join(",", containers.Select(c => c.Name)));
|
fixtureLog.Log("Selected nodes: " + string.Join(",", containers.Select(c => c.Name)));
|
||||||
return codexNodeFactory.Create(config, containers, fixtureLog, handle.Test.TimeSet);
|
return codexNodeFactory.Create(config, containers, fixtureLog, handle.Test.TimeSet);
|
||||||
}
|
}
|
||||||
|
|
||||||
private RunningContainer[] SelectRandomContainers(int number)
|
private RunningContainer[] SelectRandomContainers()
|
||||||
{
|
{
|
||||||
|
var number = handle.Test.RequiredNumberOfNodes;
|
||||||
if (number == -1) return config.CodexDeployment.CodexContainers;
|
if (number == -1) return config.CodexDeployment.CodexContainers;
|
||||||
|
|
||||||
var containers = config.CodexDeployment.CodexContainers.ToList();
|
var containers = config.CodexDeployment.CodexContainers.ToList();
|
||||||
|
|
|
@ -15,6 +15,7 @@ namespace ContinuousTests
|
||||||
{
|
{
|
||||||
this.config = config;
|
this.config = config;
|
||||||
this.cancelToken = cancelToken;
|
this.cancelToken = cancelToken;
|
||||||
|
LogReplacements = new List<BaseLogStringReplacement>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Check()
|
public void Check()
|
||||||
|
@ -28,6 +29,8 @@ namespace ContinuousTests
|
||||||
log.Log("All OK.");
|
log.Log("All OK.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public List<BaseLogStringReplacement> LogReplacements { get; }
|
||||||
|
|
||||||
private void PreflightCheck(Configuration config)
|
private void PreflightCheck(Configuration config)
|
||||||
{
|
{
|
||||||
var tests = testFactory.CreateTests();
|
var tests = testFactory.CreateTests();
|
||||||
|
@ -90,6 +93,7 @@ namespace ContinuousTests
|
||||||
if (info == null || string.IsNullOrEmpty(info.id)) return false;
|
if (info == null || string.IsNullOrEmpty(info.id)) return false;
|
||||||
|
|
||||||
log.Log($"Codex version: '{info.codex.version}' revision: '{info.codex.revision}'");
|
log.Log($"Codex version: '{info.codex.version}' revision: '{info.codex.revision}'");
|
||||||
|
LogReplacements.Add(new BaseLogStringReplacement(info.id, n.GetName()));
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
{
|
{
|
||||||
|
|
|
@ -9,16 +9,18 @@ namespace ContinuousTests
|
||||||
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 StartupChecker startupChecker;
|
||||||
private readonly CancellationToken cancelToken;
|
private readonly CancellationToken cancelToken;
|
||||||
private readonly EventWaitHandle runFinishedHandle = new EventWaitHandle(true, EventResetMode.ManualReset);
|
private readonly EventWaitHandle runFinishedHandle = new EventWaitHandle(true, EventResetMode.ManualReset);
|
||||||
|
|
||||||
public TestLoop(TaskFactory taskFactory, Configuration config, BaseLog overviewLog, Type testType, TimeSpan runsEvery, CancellationToken cancelToken)
|
public TestLoop(TaskFactory taskFactory, Configuration config, BaseLog overviewLog, Type testType, TimeSpan runsEvery, StartupChecker startupChecker, CancellationToken cancelToken)
|
||||||
{
|
{
|
||||||
this.taskFactory = taskFactory;
|
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.startupChecker = startupChecker;
|
||||||
this.cancelToken = cancelToken;
|
this.cancelToken = cancelToken;
|
||||||
Name = testType.Name;
|
Name = testType.Name;
|
||||||
}
|
}
|
||||||
|
@ -58,7 +60,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(taskFactory, config, overviewLog, handle, cancelToken);
|
var run = new SingleTestRun(taskFactory, config, overviewLog, handle, startupChecker, cancelToken);
|
||||||
|
|
||||||
runFinishedHandle.Reset();
|
runFinishedHandle.Reset();
|
||||||
run.Run(runFinishedHandle);
|
run.Run(runFinishedHandle);
|
||||||
|
|
|
@ -15,17 +15,7 @@ namespace ContinuousTests.Tests
|
||||||
[TestMoment(t: Zero)]
|
[TestMoment(t: Zero)]
|
||||||
public void UploadTestFile()
|
public void UploadTestFile()
|
||||||
{
|
{
|
||||||
var metadata = Configuration.CodexDeployment.Metadata;
|
var filesize = 80.MB();
|
||||||
var maxQuotaUseMb = metadata.StorageQuotaMB / 2;
|
|
||||||
var safeTTL = Math.Max(metadata.BlockTTL, metadata.BlockMI) + 30;
|
|
||||||
var runsPerTtl = Convert.ToInt32(safeTTL / RunTestEvery.TotalSeconds);
|
|
||||||
var filesizePerUploadMb = Math.Min(80, maxQuotaUseMb / runsPerTtl);
|
|
||||||
// This filesize should keep the quota below 50% of the node's max.
|
|
||||||
|
|
||||||
var filesize = filesizePerUploadMb.MB();
|
|
||||||
double codexDefaultBlockSize = 31 * 64 * 33;
|
|
||||||
var numberOfBlocks = Convert.ToInt64(Math.Ceiling(filesize.SizeInBytes / codexDefaultBlockSize));
|
|
||||||
Assert.That(numberOfBlocks, Is.EqualTo(1282));
|
|
||||||
|
|
||||||
file = FileManager.GenerateTestFile(filesize);
|
file = FileManager.GenerateTestFile(filesize);
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
using DistTestCore.Codex;
|
using DistTestCore.Codex;
|
||||||
|
using DistTestCore.Helpers;
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
|
|
||||||
namespace ContinuousTests.Tests
|
namespace ContinuousTests.Tests
|
||||||
|
@ -10,10 +11,24 @@ namespace ContinuousTests.Tests
|
||||||
public override TestFailMode TestFailMode => TestFailMode.AlwaysRunAllMoments;
|
public override TestFailMode TestFailMode => TestFailMode.AlwaysRunAllMoments;
|
||||||
|
|
||||||
[TestMoment(t: 0)]
|
[TestMoment(t: 0)]
|
||||||
|
public void CheckConnectivity()
|
||||||
|
{
|
||||||
|
var checker = new PeerConnectionTestHelpers(Log);
|
||||||
|
checker.AssertFullyConnected(Nodes);
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMoment(t: 10)]
|
||||||
public void CheckRoutingTables()
|
public void CheckRoutingTables()
|
||||||
{
|
{
|
||||||
var allIds = Nodes.Select(n => n.GetDebugInfo().table.localNode.nodeId).ToArray();
|
var allInfos = Nodes.Select(n =>
|
||||||
|
{
|
||||||
|
var info = n.GetDebugInfo();
|
||||||
|
Log.Log($"{n.GetName()} = {info.table.localNode.nodeId}");
|
||||||
|
Log.AddStringReplace(info.table.localNode.nodeId, n.GetName());
|
||||||
|
return info;
|
||||||
|
}).ToArray();
|
||||||
|
|
||||||
|
var allIds = allInfos.Select(i => i.table.localNode.nodeId).ToArray();
|
||||||
var errors = Nodes.Select(n => AreAllPresent(n, allIds)).Where(s => !string.IsNullOrEmpty(s)).ToArray();
|
var errors = Nodes.Select(n => AreAllPresent(n, allIds)).Where(s => !string.IsNullOrEmpty(s)).ToArray();
|
||||||
|
|
||||||
if (errors.Any())
|
if (errors.Any())
|
||||||
|
@ -30,7 +45,10 @@ namespace ContinuousTests.Tests
|
||||||
|
|
||||||
if (!expected.All(ex => known.Contains(ex)))
|
if (!expected.All(ex => known.Contains(ex)))
|
||||||
{
|
{
|
||||||
return $"Not all of '{string.Join(",", expected)}' were present in routing table: '{string.Join(",", known)}'";
|
var nl = Environment.NewLine;
|
||||||
|
return $"{nl}At node '{info.table.localNode.nodeId}'{nl}" +
|
||||||
|
$"Not all of{nl}'{string.Join(",", expected)}'{nl}" +
|
||||||
|
$"were present in routing table:{nl}'{string.Join(",", known)}'";
|
||||||
}
|
}
|
||||||
|
|
||||||
return string.Empty;
|
return string.Empty;
|
||||||
|
|
|
@ -2,5 +2,5 @@ dotnet run \
|
||||||
--kube-config=/opt/kubeconfig.yaml \
|
--kube-config=/opt/kubeconfig.yaml \
|
||||||
--codex-deployment=codex-deployment.json \
|
--codex-deployment=codex-deployment.json \
|
||||||
--keep=1 \
|
--keep=1 \
|
||||||
--stop=1 \
|
--stop=10 \
|
||||||
--dl-logs=1
|
--dl-logs=1
|
||||||
|
|
|
@ -47,12 +47,6 @@ namespace DistTestCore.Codex
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int GetDebugFutures()
|
|
||||||
{
|
|
||||||
// Some Codex images support debug/futures to count the number of open futures.
|
|
||||||
return 0; // Http().HttpGetJson<CodexDebugFutures>("debug/futures").futures;
|
|
||||||
}
|
|
||||||
|
|
||||||
public CodexDebugThresholdBreaches GetDebugThresholdBreaches()
|
public CodexDebugThresholdBreaches GetDebugThresholdBreaches()
|
||||||
{
|
{
|
||||||
return Http().HttpGetJson<CodexDebugThresholdBreaches>("debug/loop");
|
return Http().HttpGetJson<CodexDebugThresholdBreaches>("debug/loop");
|
||||||
|
@ -75,7 +69,7 @@ namespace DistTestCore.Codex
|
||||||
|
|
||||||
public string RequestStorage(CodexSalesRequestStorageRequest request, string contentId)
|
public string RequestStorage(CodexSalesRequestStorageRequest request, string contentId)
|
||||||
{
|
{
|
||||||
return Http().HttpPostJson<CodexSalesRequestStorageRequest, string>($"storage/request/{contentId}", request);
|
return Http().HttpPostJson($"storage/request/{contentId}", request);
|
||||||
}
|
}
|
||||||
|
|
||||||
public CodexStoragePurchase GetPurchaseStatus(string purchaseId)
|
public CodexStoragePurchase GetPurchaseStatus(string purchaseId)
|
||||||
|
|
|
@ -1,7 +1,4 @@
|
||||||
using KubernetesWorkflow;
|
using Newtonsoft.Json;
|
||||||
using Logging;
|
|
||||||
using Newtonsoft.Json;
|
|
||||||
using Utils;
|
|
||||||
|
|
||||||
namespace DistTestCore.Codex
|
namespace DistTestCore.Codex
|
||||||
{
|
{
|
||||||
|
|
|
@ -55,25 +55,20 @@ namespace DistTestCore
|
||||||
|
|
||||||
public TResponse HttpPostJson<TRequest, TResponse>(string route, TRequest body)
|
public TResponse HttpPostJson<TRequest, TResponse>(string route, TRequest body)
|
||||||
{
|
{
|
||||||
var response = HttpPostJson(route, body);
|
var response = PostJson(route, body);
|
||||||
var json = Time.Wait(response.Content.ReadAsStringAsync());
|
var json = Time.Wait(response.Content.ReadAsStringAsync());
|
||||||
if(!response.IsSuccessStatusCode) {
|
if (!response.IsSuccessStatusCode)
|
||||||
|
{
|
||||||
throw new HttpRequestException(json);
|
throw new HttpRequestException(json);
|
||||||
}
|
}
|
||||||
Log(GetUrl() + route, json);
|
Log(GetUrl() + route, json);
|
||||||
return TryJsonDeserialize<TResponse>(json);
|
return TryJsonDeserialize<TResponse>(json);
|
||||||
}
|
}
|
||||||
|
|
||||||
public HttpResponseMessage HttpPostJson<TRequest>(string route, TRequest body)
|
public string HttpPostJson<TRequest>(string route, TRequest body)
|
||||||
{
|
{
|
||||||
return Retry(() =>
|
var response = PostJson<TRequest>(route, body);
|
||||||
{
|
return Time.Wait(response.Content.ReadAsStringAsync());
|
||||||
using var client = GetClient();
|
|
||||||
var url = GetUrl() + route;
|
|
||||||
using var content = JsonContent.Create(body);
|
|
||||||
Log(url, JsonConvert.SerializeObject(body));
|
|
||||||
return Time.Wait(client.PostAsync(url, content));
|
|
||||||
}, $"HTTP-POST-JSON: {route}");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public string HttpPostString(string route, string body)
|
public string HttpPostString(string route, string body)
|
||||||
|
@ -122,7 +117,8 @@ namespace DistTestCore
|
||||||
public T TryJsonDeserialize<T>(string json)
|
public T TryJsonDeserialize<T>(string json)
|
||||||
{
|
{
|
||||||
var errors = new List<string>();
|
var errors = new List<string>();
|
||||||
var deserialized = JsonConvert.DeserializeObject<T>(json, new JsonSerializerSettings(){
|
var deserialized = JsonConvert.DeserializeObject<T>(json, new JsonSerializerSettings()
|
||||||
|
{
|
||||||
Error = delegate(object? sender, Serialization.ErrorEventArgs args)
|
Error = delegate(object? sender, Serialization.ErrorEventArgs args)
|
||||||
{
|
{
|
||||||
if (args.CurrentObject == args.ErrorContext.OriginalObject)
|
if (args.CurrentObject == args.ErrorContext.OriginalObject)
|
||||||
|
@ -136,15 +132,29 @@ namespace DistTestCore
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
if (errors.Count() > 0) {
|
if (errors.Count() > 0)
|
||||||
|
{
|
||||||
throw new JsonSerializationException($"Failed to deserialize JSON '{json}' with exception(s): \n{string.Join("\n", errors)}");
|
throw new JsonSerializationException($"Failed to deserialize JSON '{json}' with exception(s): \n{string.Join("\n", errors)}");
|
||||||
}
|
}
|
||||||
else if (deserialized == null) {
|
else if (deserialized == null)
|
||||||
|
{
|
||||||
throw new JsonSerializationException($"Failed to deserialize JSON '{json}': resulting deserialized object is null");
|
throw new JsonSerializationException($"Failed to deserialize JSON '{json}': resulting deserialized object is null");
|
||||||
}
|
}
|
||||||
return deserialized;
|
return deserialized;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private HttpResponseMessage PostJson<TRequest>(string route, TRequest body)
|
||||||
|
{
|
||||||
|
return Retry(() =>
|
||||||
|
{
|
||||||
|
using var client = GetClient();
|
||||||
|
var url = GetUrl() + route;
|
||||||
|
using var content = JsonContent.Create(body);
|
||||||
|
Log(url, JsonConvert.SerializeObject(body));
|
||||||
|
return Time.Wait(client.PostAsync(url, content));
|
||||||
|
}, $"HTTP-POST-JSON: {route}");
|
||||||
|
}
|
||||||
|
|
||||||
private string GetUrl()
|
private string GetUrl()
|
||||||
{
|
{
|
||||||
return $"{address.Host}:{address.Port}{baseUrl}";
|
return $"{address.Host}:{address.Port}{baseUrl}";
|
||||||
|
|
|
@ -60,6 +60,7 @@ namespace Logging
|
||||||
public virtual void AddStringReplace(string from, string to)
|
public virtual void AddStringReplace(string from, string to)
|
||||||
{
|
{
|
||||||
if (string.IsNullOrWhiteSpace(from)) return;
|
if (string.IsNullOrWhiteSpace(from)) return;
|
||||||
|
if (replacements.Any(r => r.From == from)) return;
|
||||||
replacements.Add(new BaseLogStringReplacement(from, to));
|
replacements.Add(new BaseLogStringReplacement(from, to));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -98,20 +99,20 @@ namespace Logging
|
||||||
|
|
||||||
public class BaseLogStringReplacement
|
public class BaseLogStringReplacement
|
||||||
{
|
{
|
||||||
private readonly string from;
|
|
||||||
private readonly string to;
|
|
||||||
|
|
||||||
public BaseLogStringReplacement(string from, string to)
|
public BaseLogStringReplacement(string from, string to)
|
||||||
{
|
{
|
||||||
this.from = from;
|
From = from;
|
||||||
this.to = to;
|
To = to;
|
||||||
|
|
||||||
if (string.IsNullOrEmpty(from) || string.IsNullOrEmpty(to) || from == to) throw new ArgumentException();
|
if (string.IsNullOrEmpty(from) || string.IsNullOrEmpty(to) || from == to) throw new ArgumentException();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public string From { get; }
|
||||||
|
public string To { get; }
|
||||||
|
|
||||||
public string Apply(string msg)
|
public string Apply(string msg)
|
||||||
{
|
{
|
||||||
return msg.Replace(from, to);
|
return msg.Replace(From, To);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,9 +6,11 @@
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public string FullFilename { get; set; } = "NULL";
|
||||||
|
|
||||||
protected override string GetFullName()
|
protected override string GetFullName()
|
||||||
{
|
{
|
||||||
return "NULL";
|
return FullFilename;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void Log(string message)
|
public override void Log(string message)
|
||||||
|
|
|
@ -4,6 +4,7 @@ using Utils;
|
||||||
|
|
||||||
namespace Tests.BasicTests
|
namespace Tests.BasicTests
|
||||||
{
|
{
|
||||||
|
[Ignore("Used for debugging continuous tests")]
|
||||||
[TestFixture]
|
[TestFixture]
|
||||||
public class ContinuousSubstitute : AutoBootstrapDistTest
|
public class ContinuousSubstitute : AutoBootstrapDistTest
|
||||||
{
|
{
|
||||||
|
@ -63,13 +64,13 @@ namespace Tests.BasicTests
|
||||||
while (DateTime.UtcNow < endTime)
|
while (DateTime.UtcNow < endTime)
|
||||||
{
|
{
|
||||||
CreatePeerConnectionTestHelpers().AssertFullyConnected(GetAllOnlineCodexNodes());
|
CreatePeerConnectionTestHelpers().AssertFullyConnected(GetAllOnlineCodexNodes());
|
||||||
|
CheckRoutingTables(GetAllOnlineCodexNodes());
|
||||||
|
|
||||||
if (DateTime.UtcNow > checkTime)
|
var node = RandomUtils.PickOneRandom(nodes.ToList());
|
||||||
{
|
var file = GenerateTestFile(50.MB());
|
||||||
CheckRoutingTables(GetAllOnlineCodexNodes());
|
node.UploadFile(file);
|
||||||
}
|
|
||||||
|
|
||||||
Thread.Sleep(5000);
|
Thread.Sleep(20000);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue