mirror of
https://github.com/logos-storage/logos-storage-nim-cs-dist-tests.git
synced 2026-01-03 22:13:10 +00:00
Merge branch 'master' into feature/extended-marketplace-testing
# Conflicts: # Tests/CodexReleaseTests/MarketTests/MarketplaceAutoBootstrapDistTest.cs # Tests/CodexReleaseTests/Parallelism.cs # Tests/DistTestCore/DistTest.cs
This commit is contained in:
commit
7d75cb784a
@ -4,8 +4,11 @@
|
||||
{
|
||||
public static string Between(string input, string open, string close)
|
||||
{
|
||||
var openIndex = input.IndexOf(open) + open.Length;
|
||||
var openI = input.IndexOf(open);
|
||||
if (openI == -1) return input;
|
||||
var openIndex = openI + open.Length;
|
||||
var closeIndex = input.LastIndexOf(close);
|
||||
if (closeIndex == -1) return input;
|
||||
|
||||
return input.Substring(openIndex, closeIndex - openIndex);
|
||||
}
|
||||
|
||||
@ -23,16 +23,27 @@ namespace CodexPlugin.OverwatchSupport
|
||||
converter = new CodexLogConverter(writer, config, identityMap);
|
||||
}
|
||||
|
||||
public void Finalize(string outputFilepath)
|
||||
public void FinalizeWriter()
|
||||
{
|
||||
log.Log("Finalizing Codex transcript...");
|
||||
|
||||
writer.AddHeader(CodexHeaderKey, CreateCodexHeader());
|
||||
writer.Write(outputFilepath);
|
||||
writer.Write(GetOutputFullPath());
|
||||
|
||||
log.Log("Done");
|
||||
}
|
||||
|
||||
private string GetOutputFullPath()
|
||||
{
|
||||
var outputPath = Path.GetDirectoryName(log.GetFullName());
|
||||
if (outputPath == null) throw new Exception("Logfile path is null");
|
||||
var filename = Path.GetFileNameWithoutExtension(log.GetFullName());
|
||||
if (string.IsNullOrEmpty(filename)) throw new Exception("Logfile name is null or empty");
|
||||
var outputFile = Path.Combine(outputPath, filename + "_" + config.OutputPath);
|
||||
if (!outputFile.EndsWith(".owts")) outputFile += ".owts";
|
||||
return outputFile;
|
||||
}
|
||||
|
||||
public ICodexNodeHooks CreateHooks(string nodeName)
|
||||
{
|
||||
nodeName = Str.Between(nodeName, "'", "'");
|
||||
|
||||
@ -2,11 +2,13 @@
|
||||
{
|
||||
public class CodexTranscriptWriterConfig
|
||||
{
|
||||
public CodexTranscriptWriterConfig(bool includeBlockReceivedEvents)
|
||||
public CodexTranscriptWriterConfig(string outputPath, bool includeBlockReceivedEvents)
|
||||
{
|
||||
OutputPath = outputPath;
|
||||
IncludeBlockReceivedEvents = includeBlockReceivedEvents;
|
||||
}
|
||||
|
||||
public string OutputPath { get; }
|
||||
public bool IncludeBlockReceivedEvents { get; }
|
||||
}
|
||||
}
|
||||
|
||||
@ -3,7 +3,6 @@ using CodexContractsPlugin;
|
||||
using CodexContractsPlugin.Marketplace;
|
||||
using CodexPlugin;
|
||||
using CodexTests;
|
||||
using DistTestCore;
|
||||
using GethPlugin;
|
||||
using Logging;
|
||||
using Nethereum.Hex.HexConvertors.Extensions;
|
||||
@ -14,36 +13,33 @@ namespace CodexReleaseTests.MarketTests
|
||||
{
|
||||
public abstract class MarketplaceAutoBootstrapDistTest : AutoBootstrapDistTest
|
||||
{
|
||||
private readonly Dictionary<TestLifecycle, MarketplaceHandle> handles = new Dictionary<TestLifecycle, MarketplaceHandle>();
|
||||
private MarketplaceHandle handle = null!;
|
||||
protected const int StartingBalanceTST = 1000;
|
||||
protected const int StartingBalanceEth = 10;
|
||||
|
||||
protected override void LifecycleStart(TestLifecycle lifecycle)
|
||||
[SetUp]
|
||||
public void SetupMarketplace()
|
||||
{
|
||||
base.LifecycleStart(lifecycle);
|
||||
var geth = StartGethNode(s => s.IsMiner());
|
||||
var contracts = Ci.StartCodexContracts(geth, BootstrapNode.Version);
|
||||
var monitor = SetupChainMonitor(lifecycle.Log, contracts, lifecycle.TestStartUtc);
|
||||
handles.Add(lifecycle, new MarketplaceHandle(geth, contracts, monitor));
|
||||
var monitor = SetupChainMonitor(GetTestLog(), contracts, GetTestRunTimeRange().From);
|
||||
handle = new MarketplaceHandle(geth, contracts, monitor));
|
||||
}
|
||||
|
||||
protected override void LifecycleStop(TestLifecycle lifecycle, DistTestResult result)
|
||||
[TearDown]
|
||||
public void TearDownMarketplace()
|
||||
{
|
||||
var handle = handles[lifecycle];
|
||||
if (handle.ChainMonitor != null) handle.ChainMonitor.Stop();
|
||||
|
||||
handles.Remove(lifecycle);
|
||||
base.LifecycleStop(lifecycle, result);
|
||||
}
|
||||
|
||||
protected IGethNode GetGeth()
|
||||
{
|
||||
return handles[Get()].Geth;
|
||||
return handle.Geth;
|
||||
}
|
||||
|
||||
protected ICodexContracts GetContracts()
|
||||
{
|
||||
return handles[Get()].Contracts;
|
||||
return handle.Contracts;
|
||||
}
|
||||
|
||||
protected TimeSpan GetPeriodDuration()
|
||||
|
||||
@ -12,70 +12,45 @@ using Assert = NUnit.Framework.Assert;
|
||||
namespace DistTestCore
|
||||
{
|
||||
[Parallelizable(ParallelScope.All)]
|
||||
[FixtureLifeCycle(LifeCycle.InstancePerTestCase)]
|
||||
public abstract class DistTest
|
||||
{
|
||||
private const string TestNamespacePrefix = "cdx-";
|
||||
private readonly Configuration configuration = new Configuration();
|
||||
private readonly Assembly[] testAssemblies;
|
||||
private static readonly Global global = new Global();
|
||||
private readonly FixtureLog fixtureLog;
|
||||
private readonly StatusLog statusLog;
|
||||
private readonly object lifecycleLock = new object();
|
||||
private readonly EntryPoint globalEntryPoint;
|
||||
private readonly Dictionary<string, TestLifecycle> lifecycles = new Dictionary<string, TestLifecycle>();
|
||||
private readonly string deployId;
|
||||
|
||||
private readonly TestLifecycle lifecycle;
|
||||
private readonly string deployId = NameUtils.MakeDeployId();
|
||||
|
||||
public DistTest()
|
||||
{
|
||||
var assemblies = AppDomain.CurrentDomain.GetAssemblies();
|
||||
testAssemblies = assemblies.Where(a => a.FullName!.ToLowerInvariant().Contains("test")).ToArray();
|
||||
|
||||
deployId = NameUtils.MakeDeployId();
|
||||
|
||||
var logConfig = configuration.GetLogConfig();
|
||||
var logConfig = global.Configuration.GetLogConfig();
|
||||
var startTime = DateTime.UtcNow;
|
||||
fixtureLog = FixtureLog.Create(logConfig, startTime, deployId);
|
||||
statusLog = new StatusLog(logConfig, startTime, "dist-tests", deployId);
|
||||
|
||||
globalEntryPoint = new EntryPoint(fixtureLog, configuration.GetK8sConfiguration(new DefaultK8sTimeSet(), TestNamespacePrefix), configuration.GetFileManagerFolder());
|
||||
fixtureLog.Log("Test framework revision: " + GitInfo.GetStatus());
|
||||
|
||||
lifecycle = new TestLifecycle(fixtureLog.CreateTestLog(startTime), global.Configuration,
|
||||
GetWebCallTimeSet(),
|
||||
GetK8sTimeSet(),
|
||||
Global.TestNamespacePrefix + Guid.NewGuid().ToString(),
|
||||
deployId,
|
||||
ShouldWaitForCleanup()
|
||||
);
|
||||
|
||||
Initialize(fixtureLog);
|
||||
}
|
||||
|
||||
[OneTimeSetUp]
|
||||
public void GlobalSetup()
|
||||
public static void GlobalSetup()
|
||||
{
|
||||
fixtureLog.Log($"Starting...");
|
||||
globalEntryPoint.Announce();
|
||||
|
||||
// Previous test run may have been interrupted.
|
||||
// Begin by cleaning everything up.
|
||||
try
|
||||
{
|
||||
Stopwatch.Measure(fixtureLog, "Global setup", () =>
|
||||
{
|
||||
globalEntryPoint.Tools.CreateWorkflow().DeleteNamespacesStartingWith(TestNamespacePrefix, wait: true);
|
||||
});
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
GlobalTestFailure.HasFailed = true;
|
||||
fixtureLog.Error($"Global setup cleanup failed with: {ex}");
|
||||
throw;
|
||||
}
|
||||
|
||||
fixtureLog.Log("Test framework revision: " + GitInfo.GetStatus());
|
||||
fixtureLog.Log("Global setup cleanup successful");
|
||||
global.Setup();
|
||||
}
|
||||
|
||||
[OneTimeTearDown]
|
||||
public void GlobalTearDown()
|
||||
public static void GlobalTearDown()
|
||||
{
|
||||
globalEntryPoint.Decommission(
|
||||
// There shouldn't be any of either, but clean everything up regardless.
|
||||
deleteKubernetesResources: true,
|
||||
deleteTrackedFiles: true,
|
||||
waitTillDone: true
|
||||
);
|
||||
global.TearDown();
|
||||
}
|
||||
|
||||
[SetUp]
|
||||
@ -85,18 +60,6 @@ namespace DistTestCore
|
||||
{
|
||||
Assert.Inconclusive("Skip test: Previous test failed during clean up.");
|
||||
}
|
||||
else
|
||||
{
|
||||
try
|
||||
{
|
||||
CreateNewTestLifecycle();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
fixtureLog.Error("Setup failed: " + ex);
|
||||
GlobalTestFailure.HasFailed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[TearDown]
|
||||
@ -117,18 +80,18 @@ namespace DistTestCore
|
||||
{
|
||||
get
|
||||
{
|
||||
return Get().CoreInterface;
|
||||
return lifecycle.CoreInterface;
|
||||
}
|
||||
}
|
||||
|
||||
public TrackedFile GenerateTestFile(ByteSize size, string label = "")
|
||||
{
|
||||
return Get().GenerateTestFile(size, label);
|
||||
return lifecycle.GenerateTestFile(size, label);
|
||||
}
|
||||
|
||||
public TrackedFile GenerateTestFile(Action<IGenerateOption> options, string label = "")
|
||||
{
|
||||
return Get().GenerateTestFile(options, label);
|
||||
return lifecycle.GenerateTestFile(options, label);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -137,12 +100,22 @@ namespace DistTestCore
|
||||
/// </summary>
|
||||
public void ScopedTestFiles(Action action)
|
||||
{
|
||||
Get().GetFileManager().ScopedFiles(action);
|
||||
lifecycle.GetFileManager().ScopedFiles(action);
|
||||
}
|
||||
|
||||
public ILog GetTestLog()
|
||||
{
|
||||
return Get().Log;
|
||||
return lifecycle.Log;
|
||||
}
|
||||
|
||||
public IFileManager GetFileManager()
|
||||
{
|
||||
return lifecycle.GetFileManager();
|
||||
}
|
||||
|
||||
public string GetTestNamespace()
|
||||
{
|
||||
return lifecycle.TestNamespace;
|
||||
}
|
||||
|
||||
public void Log(string msg)
|
||||
@ -159,64 +132,24 @@ namespace DistTestCore
|
||||
|
||||
public void Measure(string name, Action action)
|
||||
{
|
||||
Stopwatch.Measure(Get().Log, name, action);
|
||||
Stopwatch.Measure(lifecycle.Log, name, action);
|
||||
}
|
||||
|
||||
protected TimeRange GetTestRunTimeRange()
|
||||
{
|
||||
return new TimeRange(Get().TestStartUtc, DateTime.UtcNow);
|
||||
return new TimeRange(lifecycle.TestStartUtc, DateTime.UtcNow);
|
||||
}
|
||||
|
||||
protected virtual void Initialize(FixtureLog fixtureLog)
|
||||
{
|
||||
}
|
||||
|
||||
protected virtual void LifecycleStart(TestLifecycle lifecycle)
|
||||
{
|
||||
}
|
||||
|
||||
protected virtual void LifecycleStop(TestLifecycle lifecycle, DistTestResult testResult)
|
||||
{
|
||||
}
|
||||
|
||||
protected virtual void CollectStatusLogData(TestLifecycle lifecycle, Dictionary<string, string> data)
|
||||
{
|
||||
}
|
||||
|
||||
protected TestLifecycle Get()
|
||||
{
|
||||
lock (lifecycleLock)
|
||||
{
|
||||
return lifecycles[GetCurrentTestName()];
|
||||
}
|
||||
}
|
||||
|
||||
private void CreateNewTestLifecycle()
|
||||
{
|
||||
var testName = GetCurrentTestName();
|
||||
fixtureLog.WriteLogTag();
|
||||
Stopwatch.Measure(fixtureLog, $"Setup for {testName}", () =>
|
||||
{
|
||||
lock (lifecycleLock)
|
||||
{
|
||||
var testNamespace = TestNamespacePrefix + Guid.NewGuid().ToString();
|
||||
var lifecycle = new TestLifecycle(
|
||||
fixtureLog.CreateTestLog(),
|
||||
configuration,
|
||||
GetWebCallTimeSet(),
|
||||
GetK8sTimeSet(),
|
||||
testNamespace,
|
||||
deployId,
|
||||
ShouldWaitForCleanup());
|
||||
lifecycles.Add(testName, lifecycle);
|
||||
LifecycleStart(lifecycle);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void DisposeTestLifecycle()
|
||||
{
|
||||
var lifecycle = Get();
|
||||
var testResult = GetTestResult();
|
||||
var testDuration = lifecycle.GetTestDuration();
|
||||
var data = lifecycle.GetPluginMetadata();
|
||||
@ -228,9 +161,7 @@ namespace DistTestCore
|
||||
WriteEndTestLog(lifecycle.Log);
|
||||
|
||||
IncludeLogsOnTestFailure(lifecycle);
|
||||
LifecycleStop(lifecycle, testResult);
|
||||
lifecycle.DeleteAllResources();
|
||||
lifecycles.Remove(GetCurrentTestName());
|
||||
});
|
||||
}
|
||||
|
||||
@ -287,7 +218,7 @@ namespace DistTestCore
|
||||
var className = currentTest.ClassName;
|
||||
var methodName = currentTest.MethodName;
|
||||
|
||||
var testClasses = testAssemblies.SelectMany(a => a.GetTypes()).Where(c => c.FullName == className).ToArray();
|
||||
var testClasses = global.TestAssemblies.SelectMany(a => a.GetTypes()).Where(c => c.FullName == className).ToArray();
|
||||
var testMethods = testClasses.SelectMany(c => c.GetMethods()).Where(m => m.Name == methodName).ToArray();
|
||||
|
||||
return testMethods.Select(m => m.GetCustomAttribute<T>())
|
||||
@ -296,19 +227,24 @@ namespace DistTestCore
|
||||
.ToArray();
|
||||
}
|
||||
|
||||
protected IDownloadedLog[] DownloadAllLogs()
|
||||
{
|
||||
return lifecycle.DownloadAllLogs();
|
||||
}
|
||||
|
||||
private void IncludeLogsOnTestFailure(TestLifecycle lifecycle)
|
||||
{
|
||||
var testStatus = TestContext.CurrentContext.Result.Outcome.Status;
|
||||
if (ShouldDownloadAllLogs(testStatus))
|
||||
{
|
||||
lifecycle.Log.Log("Downloading all container logs...");
|
||||
lifecycle.DownloadAllLogs();
|
||||
DownloadAllLogs();
|
||||
}
|
||||
}
|
||||
|
||||
private bool ShouldDownloadAllLogs(TestStatus testStatus)
|
||||
{
|
||||
if (configuration.AlwaysDownloadContainerLogs) return true;
|
||||
if (global.Configuration.AlwaysDownloadContainerLogs) return true;
|
||||
if (!IsDownloadingLogsEnabled()) return false;
|
||||
if (testStatus == TestStatus.Failed)
|
||||
{
|
||||
@ -323,7 +259,7 @@ namespace DistTestCore
|
||||
return $"[{TestContext.CurrentContext.Test.Name}]";
|
||||
}
|
||||
|
||||
private DistTestResult GetTestResult()
|
||||
public DistTestResult GetTestResult()
|
||||
{
|
||||
var success = TestContext.CurrentContext.Result.Outcome.Status == TestStatus.Passed;
|
||||
var status = TestContext.CurrentContext.Result.Outcome.Status.ToString();
|
||||
|
||||
60
Tests/DistTestCore/Global.cs
Normal file
60
Tests/DistTestCore/Global.cs
Normal file
@ -0,0 +1,60 @@
|
||||
using System.Reflection;
|
||||
using Core;
|
||||
using Logging;
|
||||
|
||||
namespace DistTestCore
|
||||
{
|
||||
public class Global
|
||||
{
|
||||
public const string TestNamespacePrefix = "cdx-";
|
||||
public Configuration Configuration { get; } = new Configuration();
|
||||
|
||||
public Assembly[] TestAssemblies { get; }
|
||||
private readonly EntryPoint globalEntryPoint;
|
||||
private readonly ILog log;
|
||||
|
||||
public Global()
|
||||
{
|
||||
var assemblies = AppDomain.CurrentDomain.GetAssemblies();
|
||||
TestAssemblies = assemblies.Where(a => a.FullName!.ToLowerInvariant().Contains("test")).ToArray();
|
||||
|
||||
log = new ConsoleLog();
|
||||
globalEntryPoint = new EntryPoint(
|
||||
log,
|
||||
Configuration.GetK8sConfiguration(
|
||||
new DefaultK8sTimeSet(),
|
||||
TestNamespacePrefix
|
||||
),
|
||||
Configuration.GetFileManagerFolder()
|
||||
);
|
||||
}
|
||||
|
||||
public void Setup()
|
||||
{
|
||||
try
|
||||
{
|
||||
Stopwatch.Measure(log, "Global setup", () =>
|
||||
{
|
||||
globalEntryPoint.Announce();
|
||||
globalEntryPoint.Tools.CreateWorkflow().DeleteNamespacesStartingWith(TestNamespacePrefix, wait: true);
|
||||
});
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
GlobalTestFailure.HasFailed = true;
|
||||
log.Error($"Global setup cleanup failed with: {ex}");
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
public void TearDown()
|
||||
{
|
||||
globalEntryPoint.Decommission(
|
||||
// There shouldn't be any of either, but clean everything up regardless.
|
||||
deleteKubernetesResources: true,
|
||||
deleteTrackedFiles: true,
|
||||
waitTillDone: true
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -4,19 +4,14 @@ namespace DistTestCore.Logs
|
||||
{
|
||||
public class FixtureLog : BaseTestLog
|
||||
{
|
||||
private readonly ILog backingLog;
|
||||
private readonly string deployId;
|
||||
|
||||
public FixtureLog(ILog backingLog, string deployId)
|
||||
: base(backingLog, deployId)
|
||||
{
|
||||
this.backingLog = backingLog;
|
||||
this.deployId = deployId;
|
||||
}
|
||||
|
||||
public TestLog CreateTestLog(string name = "")
|
||||
public TestLog CreateTestLog(DateTime start, string name = "")
|
||||
{
|
||||
return TestLog.Create(this, name);
|
||||
return TestLog.Create(this, start, name);
|
||||
}
|
||||
|
||||
public static FixtureLog Create(LogConfig config, DateTime start, string deployId, string name = "")
|
||||
|
||||
@ -1,5 +1,4 @@
|
||||
using Logging;
|
||||
using System.Xml.Linq;
|
||||
|
||||
namespace DistTestCore.Logs
|
||||
{
|
||||
@ -11,9 +10,9 @@ namespace DistTestCore.Logs
|
||||
backingLog.Log($"*** Begin: {methodName}");
|
||||
}
|
||||
|
||||
public static TestLog Create(FixtureLog parentLog, string name = "")
|
||||
public static TestLog Create(FixtureLog parentLog, DateTime start, string name = "")
|
||||
{
|
||||
var methodName = NameUtils.GetTestMethodName(name);
|
||||
var methodName = NameUtils.GetTestLogFileName(start, name);
|
||||
var fullName = Path.Combine(parentLog.GetFullName(), methodName);
|
||||
var backingLog = CreateMainLog(fullName, name);
|
||||
return new TestLog(backingLog, methodName, parentLog.DeployId);
|
||||
|
||||
@ -5,6 +5,11 @@ namespace DistTestCore
|
||||
{
|
||||
public static class NameUtils
|
||||
{
|
||||
public static string GetTestLogFileName(DateTime start, string name = "")
|
||||
{
|
||||
return $"{Pad(start.Hour)}-{Pad(start.Minute)}-{Pad(start.Second)}Z_{GetTestMethodName(name)}";
|
||||
}
|
||||
|
||||
public static string GetTestMethodName(string name = "")
|
||||
{
|
||||
if (!string.IsNullOrEmpty(name)) return name;
|
||||
@ -16,7 +21,7 @@ namespace DistTestCore
|
||||
public static string GetFixtureFullName(LogConfig config, DateTime start, string name)
|
||||
{
|
||||
var folder = DetermineFolder(config, start);
|
||||
var fixtureName = GetFixtureName(name, start);
|
||||
var fixtureName = GetRawFixtureName();
|
||||
return Path.Combine(folder, fixtureName);
|
||||
}
|
||||
|
||||
@ -85,13 +90,6 @@ namespace DistTestCore
|
||||
Pad(start.Day));
|
||||
}
|
||||
|
||||
private static string GetFixtureName(string name, DateTime start)
|
||||
{
|
||||
var fixtureName = GetRawFixtureName();
|
||||
if (!string.IsNullOrEmpty(name)) fixtureName = name;
|
||||
return $"{Pad(start.Hour)}-{Pad(start.Minute)}-{Pad(start.Second)}Z_{fixtureName.Replace('.', '-')}";
|
||||
}
|
||||
|
||||
private static string Pad(int n)
|
||||
{
|
||||
return n.ToString().PadLeft(2, '0');
|
||||
|
||||
@ -1,29 +1,27 @@
|
||||
using CodexClient;
|
||||
using CodexPlugin;
|
||||
using DistTestCore;
|
||||
using NUnit.Framework;
|
||||
|
||||
namespace CodexTests
|
||||
{
|
||||
public class AutoBootstrapDistTest : CodexDistTest
|
||||
{
|
||||
private readonly Dictionary<TestLifecycle, ICodexNode> bootstrapNodes = new Dictionary<TestLifecycle, ICodexNode>();
|
||||
private bool isBooting = false;
|
||||
|
||||
protected override void LifecycleStart(TestLifecycle tl)
|
||||
public ICodexNode BootstrapNode { get; private set; } = null!;
|
||||
|
||||
[SetUp]
|
||||
public void SetupBootstrapNode()
|
||||
{
|
||||
base.LifecycleStart(tl);
|
||||
if (!bootstrapNodes.ContainsKey(tl))
|
||||
{
|
||||
isBooting = true;
|
||||
bootstrapNodes.Add(tl, StartCodex(s => s.WithName("BOOTSTRAP_" + tl.TestNamespace)));
|
||||
isBooting = false;
|
||||
}
|
||||
isBooting = true;
|
||||
BootstrapNode = StartCodex(s => s.WithName("BOOTSTRAP_" + GetTestNamespace()));
|
||||
isBooting = false;
|
||||
}
|
||||
|
||||
protected override void LifecycleStop(TestLifecycle lifecycle, DistTestResult result)
|
||||
[TearDown]
|
||||
public void TearDownBootstrapNode()
|
||||
{
|
||||
bootstrapNodes.Remove(lifecycle);
|
||||
base.LifecycleStop(lifecycle, result);
|
||||
BootstrapNode.Stop(waitTillStopped: false);
|
||||
}
|
||||
|
||||
protected override void OnCodexSetup(ICodexSetup setup)
|
||||
@ -33,18 +31,5 @@ namespace CodexTests
|
||||
var node = BootstrapNode;
|
||||
if (node != null) setup.WithBootstrapNode(node);
|
||||
}
|
||||
|
||||
protected ICodexNode BootstrapNode
|
||||
{
|
||||
get
|
||||
{
|
||||
var tl = Get();
|
||||
if (bootstrapNodes.TryGetValue(tl, out var node))
|
||||
{
|
||||
return node;
|
||||
}
|
||||
throw new InvalidOperationException("Bootstrap node not yet started.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
using BlockchainUtils;
|
||||
using CodexClient;
|
||||
using CodexClient.Hooks;
|
||||
using CodexContractsPlugin;
|
||||
using CodexNetDeployer;
|
||||
using CodexPlugin;
|
||||
@ -17,85 +16,14 @@ using Newtonsoft.Json;
|
||||
using NUnit.Framework;
|
||||
using NUnit.Framework.Constraints;
|
||||
using OverwatchTranscript;
|
||||
using Utils;
|
||||
|
||||
namespace CodexTests
|
||||
{
|
||||
public class CodexLogTrackerProvider : ICodexHooksProvider
|
||||
{
|
||||
private readonly Action<ICodexNode> addNode;
|
||||
|
||||
public CodexLogTrackerProvider(Action<ICodexNode> addNode)
|
||||
{
|
||||
this.addNode = addNode;
|
||||
}
|
||||
|
||||
// See TestLifecycle.cs DownloadAllLogs()
|
||||
public ICodexNodeHooks CreateHooks(string nodeName)
|
||||
{
|
||||
return new CodexLogTracker(addNode);
|
||||
}
|
||||
|
||||
public class CodexLogTracker : ICodexNodeHooks
|
||||
{
|
||||
private readonly Action<ICodexNode> addNode;
|
||||
|
||||
public CodexLogTracker(Action<ICodexNode> addNode)
|
||||
{
|
||||
this.addNode = addNode;
|
||||
}
|
||||
|
||||
public void OnFileDownloaded(ByteSize size, ContentId cid)
|
||||
{
|
||||
}
|
||||
|
||||
public void OnFileDownloading(ContentId cid)
|
||||
{
|
||||
}
|
||||
|
||||
public void OnFileUploaded(string uid, ByteSize size, ContentId cid)
|
||||
{
|
||||
}
|
||||
|
||||
public void OnFileUploading(string uid, ByteSize size)
|
||||
{
|
||||
}
|
||||
|
||||
public void OnNodeStarted(ICodexNode node, string peerId, string nodeId)
|
||||
{
|
||||
addNode(node);
|
||||
}
|
||||
|
||||
public void OnNodeStarting(DateTime startUtc, string image, EthAccount? ethAccount)
|
||||
{
|
||||
}
|
||||
|
||||
public void OnNodeStopping()
|
||||
{
|
||||
}
|
||||
|
||||
public void OnStorageAvailabilityCreated(StorageAvailability response)
|
||||
{
|
||||
}
|
||||
|
||||
public void OnStorageContractSubmitted(StoragePurchaseContract storagePurchaseContract)
|
||||
{
|
||||
}
|
||||
|
||||
public void OnStorageContractUpdated(StoragePurchase purchaseStatus)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class CodexDistTest : DistTest
|
||||
{
|
||||
private static readonly object _lock = new object();
|
||||
private static readonly Dictionary<TestLifecycle, CodexTranscriptWriter> writers = new Dictionary<TestLifecycle, CodexTranscriptWriter>();
|
||||
private static readonly Dictionary<TestLifecycle, BlockCache> blockCaches = new Dictionary<TestLifecycle, BlockCache>();
|
||||
|
||||
// this entire structure is not good and needs to be destroyed at the earliest convenience:
|
||||
private static readonly Dictionary<TestLifecycle, List<ICodexNode>> nodes = new Dictionary<TestLifecycle, List<ICodexNode>>();
|
||||
private readonly BlockCache blockCache = new BlockCache();
|
||||
private readonly List<ICodexNode> nodes = new List<ICodexNode>();
|
||||
private CodexTranscriptWriter? writer;
|
||||
|
||||
public CodexDistTest()
|
||||
{
|
||||
@ -105,41 +33,25 @@ namespace CodexTests
|
||||
ProjectPlugin.Load<MetricsPlugin.MetricsPlugin>();
|
||||
}
|
||||
|
||||
[SetUp]
|
||||
public void SetupCodexDistTest()
|
||||
{
|
||||
writer = SetupTranscript();
|
||||
}
|
||||
|
||||
[TearDown]
|
||||
public void TearDownCodexDistTest()
|
||||
{
|
||||
TeardownTranscript();
|
||||
}
|
||||
|
||||
protected override void Initialize(FixtureLog fixtureLog)
|
||||
{
|
||||
var localBuilder = new LocalCodexBuilder(fixtureLog);
|
||||
localBuilder.Intialize();
|
||||
localBuilder.Build();
|
||||
}
|
||||
|
||||
protected override void LifecycleStart(TestLifecycle lifecycle)
|
||||
{
|
||||
base.LifecycleStart(lifecycle);
|
||||
SetupTranscript(lifecycle);
|
||||
|
||||
Ci.AddCodexHooksProvider(new CodexLogTrackerProvider(n =>
|
||||
{
|
||||
lock (_lock)
|
||||
{
|
||||
if (!nodes.ContainsKey(lifecycle)) nodes.Add(lifecycle, new List<ICodexNode>());
|
||||
nodes[lifecycle].Add(n);
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
protected override void LifecycleStop(TestLifecycle lifecycle, DistTestResult result)
|
||||
{
|
||||
base.LifecycleStop(lifecycle, result);
|
||||
TeardownTranscript(lifecycle, result);
|
||||
|
||||
if (!result.Success)
|
||||
{
|
||||
lock (_lock)
|
||||
{
|
||||
var codexNodes = nodes[lifecycle];
|
||||
foreach (var node in codexNodes) node.DownloadLog();
|
||||
}
|
||||
}
|
||||
Ci.AddCodexHooksProvider(new CodexLogTrackerProvider(nodes.Add));
|
||||
}
|
||||
|
||||
public ICodexNode StartCodex()
|
||||
@ -170,7 +82,7 @@ namespace CodexTests
|
||||
|
||||
public IGethNode StartGethNode(Action<IGethSetup> setup)
|
||||
{
|
||||
return Ci.StartGethNode(GetBlockCache(), setup);
|
||||
return Ci.StartGethNode(blockCache, setup);
|
||||
}
|
||||
|
||||
public PeerConnectionTestHelpers CreatePeerConnectionTestHelpers()
|
||||
@ -180,7 +92,7 @@ namespace CodexTests
|
||||
|
||||
public PeerDownloadTestHelpers CreatePeerDownloadTestHelpers()
|
||||
{
|
||||
return new PeerDownloadTestHelpers(GetTestLog(), Get().GetFileManager());
|
||||
return new PeerDownloadTestHelpers(GetTestLog(), GetFileManager());
|
||||
}
|
||||
|
||||
public void AssertBalance(ICodexContracts contracts, ICodexNode codexNode, Constraint constraint, string msg = "")
|
||||
@ -258,82 +170,47 @@ namespace CodexTests
|
||||
return null;
|
||||
}
|
||||
|
||||
private void SetupTranscript(TestLifecycle lifecycle)
|
||||
private CodexTranscriptWriter? SetupTranscript()
|
||||
{
|
||||
var attr = GetTranscriptAttributeOfCurrentTest();
|
||||
if (attr == null) return;
|
||||
if (attr == null) return null;
|
||||
|
||||
var config = new CodexTranscriptWriterConfig(
|
||||
attr.OutputFilename,
|
||||
attr.IncludeBlockReceivedEvents
|
||||
);
|
||||
|
||||
var log = new LogPrefixer(lifecycle.Log, "(Transcript) ");
|
||||
var log = new LogPrefixer(GetTestLog(), "(Transcript) ");
|
||||
var writer = new CodexTranscriptWriter(log, config, Transcript.NewWriter(log));
|
||||
Ci.AddCodexHooksProvider(writer);
|
||||
lock (_lock)
|
||||
{
|
||||
writers.Add(lifecycle, writer);
|
||||
}
|
||||
return writer;
|
||||
}
|
||||
|
||||
private void TeardownTranscript(TestLifecycle lifecycle, DistTestResult result)
|
||||
private void TeardownTranscript()
|
||||
{
|
||||
var attr = GetTranscriptAttributeOfCurrentTest();
|
||||
if (attr == null) return;
|
||||
|
||||
var outputFilepath = GetOutputFullPath(lifecycle, attr);
|
||||
|
||||
CodexTranscriptWriter writer = null!;
|
||||
lock (_lock)
|
||||
{
|
||||
writer = writers[lifecycle];
|
||||
writers.Remove(lifecycle);
|
||||
}
|
||||
if (writer == null) return;
|
||||
|
||||
var result = GetTestResult();
|
||||
var log = GetTestLog();
|
||||
writer.AddResult(result.Success, result.Result);
|
||||
|
||||
try
|
||||
{
|
||||
Stopwatch.Measure(lifecycle.Log, "Transcript.ProcessLogs", () =>
|
||||
Stopwatch.Measure(log, "Transcript.ProcessLogs", () =>
|
||||
{
|
||||
writer.ProcessLogs(lifecycle.DownloadAllLogs());
|
||||
writer.ProcessLogs(DownloadAllLogs());
|
||||
});
|
||||
|
||||
Stopwatch.Measure(lifecycle.Log, $"Transcript.Finalize: {outputFilepath}", () =>
|
||||
Stopwatch.Measure(log, $"Transcript.FinalizeWriter", () =>
|
||||
{
|
||||
writer.IncludeFile(lifecycle.Log.GetFullName());
|
||||
writer.Finalize(outputFilepath);
|
||||
writer.IncludeFile(log.GetFullName() + ".log");
|
||||
writer.FinalizeWriter();
|
||||
});
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
lifecycle.Log.Error("Failure during transcript teardown: " + ex);
|
||||
log.Error("Failure during transcript teardown: " + ex);
|
||||
}
|
||||
}
|
||||
|
||||
private string GetOutputFullPath(TestLifecycle lifecycle, CreateTranscriptAttribute attr)
|
||||
{
|
||||
var outputPath = Path.GetDirectoryName(lifecycle.Log.GetFullName());
|
||||
if (outputPath == null) throw new Exception("Logfile path is null");
|
||||
var filename = Path.GetFileNameWithoutExtension(lifecycle.Log.GetFullName());
|
||||
if (string.IsNullOrEmpty(filename)) throw new Exception("Logfile name is null or empty");
|
||||
var outputFile = Path.Combine(outputPath, filename + "_" + attr.OutputFilename);
|
||||
if (!outputFile.EndsWith(".owts")) outputFile += ".owts";
|
||||
return outputFile;
|
||||
}
|
||||
|
||||
private BlockCache GetBlockCache()
|
||||
{
|
||||
var lifecycle = Get();
|
||||
lock (_lock)
|
||||
{
|
||||
if (!blockCaches.ContainsKey(lifecycle))
|
||||
{
|
||||
blockCaches[lifecycle] = new BlockCache();
|
||||
}
|
||||
}
|
||||
return blockCaches[lifecycle];
|
||||
}
|
||||
}
|
||||
|
||||
[AttributeUsage(AttributeTargets.Method, AllowMultiple = false)]
|
||||
|
||||
73
Tests/ExperimentalTests/CodexLogTrackerProvider.cs
Normal file
73
Tests/ExperimentalTests/CodexLogTrackerProvider.cs
Normal file
@ -0,0 +1,73 @@
|
||||
using CodexClient;
|
||||
using CodexClient.Hooks;
|
||||
using Utils;
|
||||
|
||||
namespace CodexTests
|
||||
{
|
||||
public class CodexLogTrackerProvider : ICodexHooksProvider
|
||||
{
|
||||
private readonly Action<ICodexNode> addNode;
|
||||
|
||||
public CodexLogTrackerProvider(Action<ICodexNode> addNode)
|
||||
{
|
||||
this.addNode = addNode;
|
||||
}
|
||||
|
||||
// See TestLifecycle.cs DownloadAllLogs()
|
||||
public ICodexNodeHooks CreateHooks(string nodeName)
|
||||
{
|
||||
return new CodexLogTracker(addNode);
|
||||
}
|
||||
|
||||
public class CodexLogTracker : ICodexNodeHooks
|
||||
{
|
||||
private readonly Action<ICodexNode> addNode;
|
||||
|
||||
public CodexLogTracker(Action<ICodexNode> addNode)
|
||||
{
|
||||
this.addNode = addNode;
|
||||
}
|
||||
|
||||
public void OnFileDownloaded(ByteSize size, ContentId cid)
|
||||
{
|
||||
}
|
||||
|
||||
public void OnFileDownloading(ContentId cid)
|
||||
{
|
||||
}
|
||||
|
||||
public void OnFileUploaded(string uid, ByteSize size, ContentId cid)
|
||||
{
|
||||
}
|
||||
|
||||
public void OnFileUploading(string uid, ByteSize size)
|
||||
{
|
||||
}
|
||||
|
||||
public void OnNodeStarted(ICodexNode node, string peerId, string nodeId)
|
||||
{
|
||||
addNode(node);
|
||||
}
|
||||
|
||||
public void OnNodeStarting(DateTime startUtc, string image, EthAccount? ethAccount)
|
||||
{
|
||||
}
|
||||
|
||||
public void OnNodeStopping()
|
||||
{
|
||||
}
|
||||
|
||||
public void OnStorageAvailabilityCreated(StorageAvailability response)
|
||||
{
|
||||
}
|
||||
|
||||
public void OnStorageContractSubmitted(StoragePurchaseContract storagePurchaseContract)
|
||||
{
|
||||
}
|
||||
|
||||
public void OnStorageContractUpdated(StoragePurchase purchaseStatus)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user