2023-09-19 14:22:07 +00:00
|
|
|
|
using CodexContractsPlugin;
|
2023-09-28 10:22:35 +00:00
|
|
|
|
using CodexNetDeployer;
|
2023-09-19 14:22:07 +00:00
|
|
|
|
using CodexPlugin;
|
2024-07-25 14:00:51 +00:00
|
|
|
|
using CodexPlugin.OverwatchSupport;
|
2023-11-12 09:36:48 +00:00
|
|
|
|
using CodexTests.Helpers;
|
2023-09-20 11:56:01 +00:00
|
|
|
|
using Core;
|
2023-09-13 12:24:43 +00:00
|
|
|
|
using DistTestCore;
|
|
|
|
|
using DistTestCore.Helpers;
|
2023-09-28 10:22:35 +00:00
|
|
|
|
using DistTestCore.Logs;
|
2024-07-26 06:39:27 +00:00
|
|
|
|
using Logging;
|
2024-06-06 07:54:50 +00:00
|
|
|
|
using MetricsPlugin;
|
|
|
|
|
using Newtonsoft.Json;
|
2024-07-26 08:11:29 +00:00
|
|
|
|
using NUnit.Framework;
|
2023-09-19 14:22:07 +00:00
|
|
|
|
using NUnit.Framework.Constraints;
|
2024-07-25 14:00:51 +00:00
|
|
|
|
using OverwatchTranscript;
|
2023-09-13 12:24:43 +00:00
|
|
|
|
|
2023-10-09 14:59:52 +00:00
|
|
|
|
namespace CodexTests
|
2023-09-13 12:24:43 +00:00
|
|
|
|
{
|
|
|
|
|
public class CodexDistTest : DistTest
|
|
|
|
|
{
|
2024-07-25 14:00:51 +00:00
|
|
|
|
private static readonly Dictionary<TestLifecycle, CodexTranscriptWriter> writers = new Dictionary<TestLifecycle, CodexTranscriptWriter>();
|
|
|
|
|
|
2023-09-20 11:56:01 +00:00
|
|
|
|
public CodexDistTest()
|
|
|
|
|
{
|
|
|
|
|
ProjectPlugin.Load<CodexPlugin.CodexPlugin>();
|
|
|
|
|
ProjectPlugin.Load<CodexContractsPlugin.CodexContractsPlugin>();
|
|
|
|
|
ProjectPlugin.Load<GethPlugin.GethPlugin>();
|
|
|
|
|
ProjectPlugin.Load<MetricsPlugin.MetricsPlugin>();
|
|
|
|
|
}
|
|
|
|
|
|
2023-09-28 10:22:35 +00:00
|
|
|
|
protected override void Initialize(FixtureLog fixtureLog)
|
|
|
|
|
{
|
|
|
|
|
var localBuilder = new LocalCodexBuilder(fixtureLog);
|
|
|
|
|
localBuilder.Intialize();
|
|
|
|
|
localBuilder.Build();
|
|
|
|
|
}
|
|
|
|
|
|
2024-07-25 14:00:51 +00:00
|
|
|
|
protected override void LifecycleStart(TestLifecycle lifecycle)
|
|
|
|
|
{
|
|
|
|
|
base.LifecycleStart(lifecycle);
|
2024-07-26 08:11:29 +00:00
|
|
|
|
SetupTranscript(lifecycle);
|
2024-07-25 14:00:51 +00:00
|
|
|
|
}
|
|
|
|
|
|
2024-07-26 08:11:29 +00:00
|
|
|
|
protected override void LifecycleStop(TestLifecycle lifecycle, DistTestResult result)
|
2024-07-25 14:00:51 +00:00
|
|
|
|
{
|
2024-07-26 08:11:29 +00:00
|
|
|
|
base.LifecycleStop(lifecycle, result);
|
|
|
|
|
TeardownTranscript(lifecycle, result);
|
2024-07-25 14:00:51 +00:00
|
|
|
|
}
|
|
|
|
|
|
2024-05-09 07:32:48 +00:00
|
|
|
|
public ICodexNode StartCodex()
|
2023-09-13 12:24:43 +00:00
|
|
|
|
{
|
2024-05-09 07:32:48 +00:00
|
|
|
|
return StartCodex(s => { });
|
2023-09-13 12:24:43 +00:00
|
|
|
|
}
|
|
|
|
|
|
2024-05-09 07:32:48 +00:00
|
|
|
|
public ICodexNode StartCodex(Action<ICodexSetup> setup)
|
2023-09-13 12:24:43 +00:00
|
|
|
|
{
|
2024-05-09 07:32:48 +00:00
|
|
|
|
return StartCodex(1, setup)[0];
|
2023-09-13 12:24:43 +00:00
|
|
|
|
}
|
|
|
|
|
|
2024-05-09 07:32:48 +00:00
|
|
|
|
public ICodexNodeGroup StartCodex(int numberOfNodes)
|
2023-09-13 12:24:43 +00:00
|
|
|
|
{
|
2024-05-09 07:32:48 +00:00
|
|
|
|
return StartCodex(numberOfNodes, s => { });
|
2023-09-13 12:24:43 +00:00
|
|
|
|
}
|
|
|
|
|
|
2024-05-09 07:32:48 +00:00
|
|
|
|
public ICodexNodeGroup StartCodex(int numberOfNodes, Action<ICodexSetup> setup)
|
2023-09-13 12:24:43 +00:00
|
|
|
|
{
|
2023-09-20 10:02:32 +00:00
|
|
|
|
var group = Ci.StartCodexNodes(numberOfNodes, s =>
|
2023-09-13 12:24:43 +00:00
|
|
|
|
{
|
|
|
|
|
setup(s);
|
|
|
|
|
OnCodexSetup(s);
|
|
|
|
|
});
|
2024-06-12 13:28:08 +00:00
|
|
|
|
|
2023-09-13 12:24:43 +00:00
|
|
|
|
return group;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public PeerConnectionTestHelpers CreatePeerConnectionTestHelpers()
|
|
|
|
|
{
|
|
|
|
|
return new PeerConnectionTestHelpers(GetTestLog());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public PeerDownloadTestHelpers CreatePeerDownloadTestHelpers()
|
|
|
|
|
{
|
|
|
|
|
return new PeerDownloadTestHelpers(GetTestLog(), Get().GetFileManager());
|
|
|
|
|
}
|
|
|
|
|
|
2023-10-30 12:30:14 +00:00
|
|
|
|
public void AssertBalance(ICodexContracts contracts, ICodexNode codexNode, Constraint constraint, string msg = "")
|
2023-09-19 14:22:07 +00:00
|
|
|
|
{
|
2023-10-30 12:30:14 +00:00
|
|
|
|
AssertHelpers.RetryAssert(constraint, () => contracts.GetTestTokenBalance(codexNode), nameof(AssertBalance) + msg);
|
2023-09-19 14:22:07 +00:00
|
|
|
|
}
|
|
|
|
|
|
2023-12-12 13:18:26 +00:00
|
|
|
|
public void CheckLogForErrors(params ICodexNode[] nodes)
|
|
|
|
|
{
|
|
|
|
|
foreach (var node in nodes) CheckLogForErrors(node);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void CheckLogForErrors(ICodexNode node)
|
|
|
|
|
{
|
2024-03-20 10:11:59 +00:00
|
|
|
|
Log($"Checking {node.GetName()} log for errors.");
|
2023-12-12 13:18:26 +00:00
|
|
|
|
var log = Ci.DownloadLog(node);
|
|
|
|
|
|
|
|
|
|
log.AssertLogDoesNotContain("Block validation failed");
|
|
|
|
|
log.AssertLogDoesNotContain("ERR ");
|
|
|
|
|
}
|
|
|
|
|
|
2024-06-06 07:54:50 +00:00
|
|
|
|
public void LogNodeStatus(ICodexNode node, IMetricsAccess? metrics = null)
|
|
|
|
|
{
|
|
|
|
|
Log("Status for " + node.GetName() + Environment.NewLine +
|
2024-06-07 15:07:35 +00:00
|
|
|
|
GetBasicNodeStatus(node));
|
2024-06-06 07:54:50 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private string GetBasicNodeStatus(ICodexNode node)
|
|
|
|
|
{
|
|
|
|
|
return JsonConvert.SerializeObject(node.GetDebugInfo(), Formatting.Indented) + Environment.NewLine +
|
|
|
|
|
node.Space().ToString() + Environment.NewLine;
|
|
|
|
|
}
|
|
|
|
|
|
2024-06-07 15:07:35 +00:00
|
|
|
|
// Disabled for now: Makes huge log files!
|
|
|
|
|
//private string GetNodeMetrics(IMetricsAccess? metrics)
|
|
|
|
|
//{
|
|
|
|
|
// if (metrics == null) return "No metrics enabled";
|
|
|
|
|
// var m = metrics.GetAllMetrics();
|
|
|
|
|
// if (m == null) return "No metrics received";
|
|
|
|
|
// return m.AsCsv();
|
|
|
|
|
//}
|
2024-06-06 07:54:50 +00:00
|
|
|
|
|
2023-09-13 12:24:43 +00:00
|
|
|
|
protected virtual void OnCodexSetup(ICodexSetup setup)
|
|
|
|
|
{
|
|
|
|
|
}
|
2024-07-26 08:11:29 +00:00
|
|
|
|
|
2024-07-31 07:50:02 +00:00
|
|
|
|
private CreateTranscriptAttribute? GetTranscriptAttributeOfCurrentTest()
|
|
|
|
|
{
|
|
|
|
|
var attrs = GetCurrentTestMethodAttribute<CreateTranscriptAttribute>();
|
|
|
|
|
if (attrs.Any()) return attrs.Single();
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
2024-07-26 08:11:29 +00:00
|
|
|
|
private void SetupTranscript(TestLifecycle lifecycle)
|
|
|
|
|
{
|
2024-08-21 07:53:20 +00:00
|
|
|
|
var attr = GetTranscriptAttributeOfCurrentTest();
|
|
|
|
|
if (attr == null) return;
|
|
|
|
|
|
|
|
|
|
var config = new CodexTranscriptWriterConfig(
|
|
|
|
|
attr.IncludeBlockReceivedEvents
|
|
|
|
|
);
|
2024-07-26 08:11:29 +00:00
|
|
|
|
|
2024-08-01 08:39:06 +00:00
|
|
|
|
var log = new LogPrefixer(lifecycle.Log, "(Transcript) ");
|
2024-08-21 07:53:20 +00:00
|
|
|
|
var writer = new CodexTranscriptWriter(log, config, Transcript.NewWriter(log));
|
2024-07-26 08:11:29 +00:00
|
|
|
|
Ci.SetCodexHooksProvider(writer);
|
|
|
|
|
writers.Add(lifecycle, writer);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void TeardownTranscript(TestLifecycle lifecycle, DistTestResult result)
|
|
|
|
|
{
|
2024-07-31 07:50:02 +00:00
|
|
|
|
var attr = GetTranscriptAttributeOfCurrentTest();
|
|
|
|
|
if (attr == null) return;
|
|
|
|
|
|
|
|
|
|
var outputFilepath = GetOutputFullPath(lifecycle, attr);
|
2024-07-26 08:11:29 +00:00
|
|
|
|
|
|
|
|
|
var writer = writers[lifecycle];
|
|
|
|
|
writers.Remove(lifecycle);
|
|
|
|
|
|
|
|
|
|
writer.AddResult(result.Success, result.Result);
|
|
|
|
|
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
Stopwatch.Measure(lifecycle.Log, "Transcript.ProcessLogs", () =>
|
|
|
|
|
{
|
|
|
|
|
writer.ProcessLogs(lifecycle.DownloadAllLogs());
|
|
|
|
|
});
|
|
|
|
|
|
2024-07-31 07:50:02 +00:00
|
|
|
|
Stopwatch.Measure(lifecycle.Log, $"Transcript.Finalize: {outputFilepath}", () =>
|
2024-07-26 08:11:29 +00:00
|
|
|
|
{
|
|
|
|
|
writer.IncludeFile(lifecycle.Log.LogFile.FullFilename);
|
2024-07-31 07:50:02 +00:00
|
|
|
|
writer.Finalize(outputFilepath);
|
2024-07-26 08:11:29 +00:00
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
{
|
|
|
|
|
lifecycle.Log.Error("Failure during transcript teardown: " + ex);
|
|
|
|
|
}
|
|
|
|
|
}
|
2024-07-31 07:50:02 +00:00
|
|
|
|
|
|
|
|
|
private string GetOutputFullPath(TestLifecycle lifecycle, CreateTranscriptAttribute attr)
|
|
|
|
|
{
|
|
|
|
|
var outputPath = Path.GetDirectoryName(lifecycle.Log.LogFile.FullFilename);
|
|
|
|
|
if (outputPath == null) throw new Exception("Logfile path is null");
|
2024-07-31 12:49:42 +00:00
|
|
|
|
var filename = Path.GetFileNameWithoutExtension(lifecycle.Log.LogFile.FullFilename);
|
|
|
|
|
if (string.IsNullOrEmpty(filename)) throw new Exception("Logfile name is null or empty");
|
|
|
|
|
var outputFile = Path.Combine(outputPath, filename + "_" + attr.OutputFilename);
|
2024-07-31 07:50:02 +00:00
|
|
|
|
if (!outputFile.EndsWith(".owts")) outputFile += ".owts";
|
|
|
|
|
return outputFile;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[AttributeUsage(AttributeTargets.Method, AllowMultiple = false)]
|
|
|
|
|
public class CreateTranscriptAttribute : PropertyAttribute
|
|
|
|
|
{
|
2024-08-21 07:53:20 +00:00
|
|
|
|
public CreateTranscriptAttribute(string outputFilename, bool includeBlockReceivedEvents = true)
|
2024-07-31 07:50:02 +00:00
|
|
|
|
{
|
|
|
|
|
OutputFilename = outputFilename;
|
2024-08-21 07:53:20 +00:00
|
|
|
|
IncludeBlockReceivedEvents = includeBlockReceivedEvents;
|
2024-07-31 07:50:02 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public string OutputFilename { get; }
|
2024-08-21 07:53:20 +00:00
|
|
|
|
public bool IncludeBlockReceivedEvents { get; }
|
2023-09-13 12:24:43 +00:00
|
|
|
|
}
|
|
|
|
|
}
|