mirror of
https://github.com/logos-storage/logos-storage-nim-cs-dist-tests.git
synced 2026-01-03 14:03:09 +00:00
while better the new plan is still a mess
This commit is contained in:
parent
7eb3bbd1de
commit
2dfdfac2bb
@ -23,16 +23,27 @@ namespace CodexPlugin.OverwatchSupport
|
||||
converter = new CodexLogConverter(writer, config, identityMap);
|
||||
}
|
||||
|
||||
public void Finalize(string outputFilepath)
|
||||
public void Finalize()
|
||||
{
|
||||
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.OutputFilename);
|
||||
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 outputFilename, bool includeBlockReceivedEvents)
|
||||
{
|
||||
OutputFilename = outputFilename;
|
||||
IncludeBlockReceivedEvents = includeBlockReceivedEvents;
|
||||
}
|
||||
|
||||
public string OutputFilename { get; }
|
||||
public bool IncludeBlockReceivedEvents { get; }
|
||||
}
|
||||
}
|
||||
|
||||
@ -10,18 +10,41 @@ using Utils;
|
||||
|
||||
namespace CodexReleaseTests.MarketTests
|
||||
{
|
||||
public class MarketplaceTestComponent : ILifecycleComponent
|
||||
{
|
||||
public IGethNode Geth { get; }
|
||||
public ICodexContracts Contracts { get; }
|
||||
|
||||
public void Start(ILifecycleComponentAccess access)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public void Stop(ILifecycleComponentAccess access, DistTestResult result)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
|
||||
public abstract class MarketplaceAutoBootstrapDistTest : AutoBootstrapDistTest
|
||||
{
|
||||
private readonly Dictionary<TestLifecycle, MarketplaceHandle> handles = new Dictionary<TestLifecycle, MarketplaceHandle>();
|
||||
protected const int StartingBalanceTST = 1000;
|
||||
protected const int StartingBalanceEth = 10;
|
||||
|
||||
protected override void CreateComponents(ILifecycleComponentCollector collector)
|
||||
{
|
||||
base.CreateComponents(collector);
|
||||
|
||||
|
||||
collector.AddComponent(new MarketplaceTestComponent());
|
||||
}
|
||||
|
||||
protected override void LifecycleStart(TestLifecycle lifecycle)
|
||||
{
|
||||
base.LifecycleStart(lifecycle);
|
||||
var geth = StartGethNode(s => s.IsMiner());
|
||||
var contracts = Ci.StartCodexContracts(geth, BootstrapNode.Version);
|
||||
handles.Add(lifecycle, new MarketplaceHandle(geth, contracts));
|
||||
handles.Add(lifecycle, new MarketplaceTestComponent(geth, contracts));
|
||||
}
|
||||
|
||||
protected override void LifecycleStop(TestLifecycle lifecycle, DistTestResult result)
|
||||
@ -323,17 +346,5 @@ namespace CodexReleaseTests.MarketTests
|
||||
public SlotFilledEventDTO SlotFilledEvent { get; }
|
||||
public ICodexNode Host { get; }
|
||||
}
|
||||
|
||||
private class MarketplaceHandle
|
||||
{
|
||||
public MarketplaceHandle(IGethNode geth, ICodexContracts contracts)
|
||||
{
|
||||
Geth = geth;
|
||||
Contracts = contracts;
|
||||
}
|
||||
|
||||
public IGethNode Geth { get; }
|
||||
public ICodexContracts Contracts { get; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -19,9 +19,8 @@ namespace DistTestCore
|
||||
private readonly Assembly[] testAssemblies;
|
||||
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 DistTestLifecycleComponents lifecycleComponents = new DistTestLifecycleComponents();
|
||||
private readonly string deployId;
|
||||
|
||||
public DistTest()
|
||||
@ -89,7 +88,12 @@ namespace DistTestCore
|
||||
{
|
||||
try
|
||||
{
|
||||
CreateNewTestLifecycle();
|
||||
var testName = GetCurrentTestName();
|
||||
fixtureLog.WriteLogTag();
|
||||
Stopwatch.Measure(fixtureLog, $"Setup for {testName}", () =>
|
||||
{
|
||||
lifecycleComponents.Setup(testName, CreateComponents);
|
||||
});
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
@ -104,7 +108,7 @@ namespace DistTestCore
|
||||
{
|
||||
try
|
||||
{
|
||||
DisposeTestLifecycle();
|
||||
Stopwatch.Measure(fixtureLog, $"Teardown for {GetCurrentTestName()}", DisposeTestLifecycle);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
@ -171,80 +175,49 @@ namespace DistTestCore
|
||||
{
|
||||
}
|
||||
|
||||
protected virtual void LifecycleStart(TestLifecycle lifecycle)
|
||||
protected virtual void CreateComponents(ILifecycleComponentCollector collector)
|
||||
{
|
||||
var testNamespace = TestNamespacePrefix + Guid.NewGuid().ToString();
|
||||
var lifecycle = new TestLifecycle(
|
||||
fixtureLog.CreateTestLog(),
|
||||
configuration,
|
||||
GetWebCallTimeSet(),
|
||||
GetK8sTimeSet(),
|
||||
testNamespace,
|
||||
GetCurrentTestName(),
|
||||
deployId,
|
||||
ShouldWaitForCleanup());
|
||||
|
||||
collector.AddComponent(lifecycle);
|
||||
}
|
||||
|
||||
protected virtual void DestroyComponents(TestLifecycle lifecycle, DistTestResult testResult)
|
||||
{
|
||||
}
|
||||
|
||||
protected virtual void LifecycleStop(TestLifecycle lifecycle, DistTestResult testResult)
|
||||
public T Get<T>() where T : ILifecycleComponent
|
||||
{
|
||||
return lifecycleComponents.Get<T>(GetCurrentTestName());
|
||||
}
|
||||
|
||||
protected virtual void CollectStatusLogData(TestLifecycle lifecycle, Dictionary<string, string> data)
|
||||
private TestLifecycle Get()
|
||||
{
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
});
|
||||
return Get<TestLifecycle>();
|
||||
}
|
||||
|
||||
private void DisposeTestLifecycle()
|
||||
{
|
||||
var testName = GetCurrentTestName();
|
||||
var results = GetTestResult();
|
||||
var lifecycle = Get();
|
||||
var testResult = GetTestResult();
|
||||
var testDuration = lifecycle.GetTestDuration();
|
||||
var data = lifecycle.GetPluginMetadata();
|
||||
CollectStatusLogData(lifecycle, data);
|
||||
fixtureLog.Log($"{GetCurrentTestName()} = {testResult} ({testDuration})");
|
||||
statusLog.ConcludeTest(testResult, testDuration, data);
|
||||
Stopwatch.Measure(fixtureLog, $"Teardown for {GetCurrentTestName()}", () =>
|
||||
{
|
||||
WriteEndTestLog(lifecycle.Log);
|
||||
fixtureLog.Log($"{GetCurrentTestName()} = {results} ({testDuration})");
|
||||
statusLog.ConcludeTest(results, testDuration, data);
|
||||
|
||||
IncludeLogsOnTestFailure(lifecycle);
|
||||
LifecycleStop(lifecycle, testResult);
|
||||
lifecycle.DeleteAllResources();
|
||||
lifecycles.Remove(GetCurrentTestName());
|
||||
});
|
||||
lifecycleComponents.TearDown(testName, results);
|
||||
}
|
||||
|
||||
private void WriteEndTestLog(TestLog log)
|
||||
{
|
||||
var result = TestContext.CurrentContext.Result;
|
||||
|
||||
Log($"*** Finished: {GetCurrentTestName()} = {result.Outcome.Status}");
|
||||
if (!string.IsNullOrEmpty(result.Message))
|
||||
{
|
||||
Log(result.Message);
|
||||
Log($"{result.StackTrace}");
|
||||
}
|
||||
}
|
||||
|
||||
private IWebCallTimeSet GetWebCallTimeSet()
|
||||
{
|
||||
@ -296,28 +269,6 @@ namespace DistTestCore
|
||||
.ToArray();
|
||||
}
|
||||
|
||||
private void IncludeLogsOnTestFailure(TestLifecycle lifecycle)
|
||||
{
|
||||
var testStatus = TestContext.CurrentContext.Result.Outcome.Status;
|
||||
if (ShouldDownloadAllLogs(testStatus))
|
||||
{
|
||||
lifecycle.Log.Log("Downloading all container logs...");
|
||||
lifecycle.DownloadAllLogs();
|
||||
}
|
||||
}
|
||||
|
||||
private bool ShouldDownloadAllLogs(TestStatus testStatus)
|
||||
{
|
||||
if (configuration.AlwaysDownloadContainerLogs) return true;
|
||||
if (!IsDownloadingLogsEnabled()) return false;
|
||||
if (testStatus == TestStatus.Failed)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private string GetCurrentTestName()
|
||||
{
|
||||
return $"[{TestContext.CurrentContext.Test.Name}]";
|
||||
@ -328,7 +279,8 @@ namespace DistTestCore
|
||||
var success = TestContext.CurrentContext.Result.Outcome.Status == TestStatus.Passed;
|
||||
var status = TestContext.CurrentContext.Result.Outcome.Status.ToString();
|
||||
var result = TestContext.CurrentContext.Result.Message;
|
||||
return new DistTestResult(success, status, result ?? string.Empty);
|
||||
var trace = TestContext.CurrentContext.Result.StackTrace;
|
||||
return new DistTestResult(success, status, result ?? string.Empty, trace ?? string.Empty);
|
||||
}
|
||||
|
||||
private bool IsDownloadingLogsEnabled()
|
||||
@ -339,16 +291,18 @@ namespace DistTestCore
|
||||
|
||||
public class DistTestResult
|
||||
{
|
||||
public DistTestResult(bool success, string status, string result)
|
||||
public DistTestResult(bool success, string status, string result, string trace)
|
||||
{
|
||||
Success = success;
|
||||
Status = status;
|
||||
Result = result;
|
||||
Trace = trace;
|
||||
}
|
||||
|
||||
public bool Success { get; }
|
||||
public string Status { get; }
|
||||
public string Result { get; }
|
||||
public string Trace { get; }
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
|
||||
97
Tests/DistTestCore/DistTestLifecycleComponents.cs
Normal file
97
Tests/DistTestCore/DistTestLifecycleComponents.cs
Normal file
@ -0,0 +1,97 @@
|
||||
namespace DistTestCore
|
||||
{
|
||||
public interface ILifecycleComponent
|
||||
{
|
||||
void Start(ILifecycleComponentAccess access);
|
||||
void Stop(ILifecycleComponentAccess access, DistTestResult result);
|
||||
}
|
||||
|
||||
public interface ILifecycleComponentCollector
|
||||
{
|
||||
void AddComponent(ILifecycleComponent component);
|
||||
}
|
||||
|
||||
public interface ILifecycleComponentAccess
|
||||
{
|
||||
T Get<T>() where T : ILifecycleComponent;
|
||||
}
|
||||
|
||||
public class DistTestLifecycleComponents
|
||||
{
|
||||
private readonly object _lock = new object();
|
||||
private readonly Dictionary<string, Dictionary<Type, ILifecycleComponent>> components = new();
|
||||
|
||||
public void Setup(string testName, Action<ILifecycleComponentCollector> initializer)
|
||||
{
|
||||
var newComponents = new Dictionary<Type, ILifecycleComponent>();
|
||||
lock (_lock)
|
||||
{
|
||||
components.Add(testName, newComponents);
|
||||
var collector = new Collector(newComponents);
|
||||
initializer(collector);
|
||||
}
|
||||
|
||||
var access = new ScopedAccess(this, testName);
|
||||
foreach (var component in newComponents.Values)
|
||||
{
|
||||
component.Start(access);
|
||||
}
|
||||
}
|
||||
|
||||
public T Get<T>(string testName) where T : ILifecycleComponent
|
||||
{
|
||||
var type = typeof(T);
|
||||
lock (_lock)
|
||||
{
|
||||
return (T)components[testName][type];
|
||||
}
|
||||
}
|
||||
|
||||
public void TearDown(string testName, DistTestResult result)
|
||||
{
|
||||
var access = new ScopedAccess(this, testName);
|
||||
var closingComponents = components[testName];
|
||||
foreach (var component in closingComponents.Values)
|
||||
{
|
||||
component.Stop(access, result);
|
||||
}
|
||||
|
||||
lock (_lock)
|
||||
{
|
||||
components.Remove(testName);
|
||||
}
|
||||
}
|
||||
|
||||
private class Collector : ILifecycleComponentCollector
|
||||
{
|
||||
private readonly Dictionary<Type, ILifecycleComponent> components;
|
||||
|
||||
public Collector(Dictionary<Type, ILifecycleComponent> components)
|
||||
{
|
||||
this.components = components;
|
||||
}
|
||||
|
||||
public void AddComponent(ILifecycleComponent component)
|
||||
{
|
||||
components.Add(component.GetType(), component);
|
||||
}
|
||||
}
|
||||
|
||||
private class ScopedAccess : ILifecycleComponentAccess
|
||||
{
|
||||
private readonly DistTestLifecycleComponents parent;
|
||||
private readonly string testName;
|
||||
|
||||
public ScopedAccess(DistTestLifecycleComponents parent, string testName)
|
||||
{
|
||||
this.parent = parent;
|
||||
this.testName = testName;
|
||||
}
|
||||
|
||||
public T Get<T>() where T : ILifecycleComponent
|
||||
{
|
||||
return parent.Get<T>(testName);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -4,26 +4,25 @@ 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 = "")
|
||||
{
|
||||
return TestLog.Create(this, name);
|
||||
var result = TestLog.Create(this, name);
|
||||
result.Log(NameUtils.GetRawFixtureName());
|
||||
return result;
|
||||
}
|
||||
|
||||
public static FixtureLog Create(LogConfig config, DateTime start, string deployId, string name = "")
|
||||
{
|
||||
var fullName = NameUtils.GetFixtureFullName(config, start, name);
|
||||
var log = CreateMainLog(fullName, name);
|
||||
return new FixtureLog(log, deployId);
|
||||
var result = new FixtureLog(log, deployId);
|
||||
result.Log(NameUtils.GetRawFixtureName());
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,5 +1,4 @@
|
||||
using Logging;
|
||||
using System.Xml.Linq;
|
||||
|
||||
namespace DistTestCore.Logs
|
||||
{
|
||||
@ -8,7 +7,6 @@ namespace DistTestCore.Logs
|
||||
public TestLog(ILog backingLog, string methodName, string deployId, string name = "")
|
||||
: base(backingLog, deployId)
|
||||
{
|
||||
backingLog.Log($"*** Begin: {methodName}");
|
||||
}
|
||||
|
||||
public static TestLog Create(FixtureLog parentLog, string name = "")
|
||||
|
||||
@ -10,22 +10,24 @@ using WebUtils;
|
||||
|
||||
namespace DistTestCore
|
||||
{
|
||||
public class TestLifecycle : IK8sHooks
|
||||
public class TestLifecycle : IK8sHooks, ILifecycleComponent
|
||||
{
|
||||
private const string TestsType = "dist-tests";
|
||||
private readonly EntryPoint entryPoint;
|
||||
private readonly Dictionary<string, string> metadata;
|
||||
private readonly List<RunningPod> runningContainers = new();
|
||||
private readonly string testName;
|
||||
private readonly string deployId;
|
||||
private readonly List<IDownloadedLog> stoppedContainerLogs = new List<IDownloadedLog>();
|
||||
|
||||
public TestLifecycle(TestLog log, Configuration configuration, IWebCallTimeSet webCallTimeSet, IK8sTimeSet k8sTimeSet, string testNamespace, string deployId, bool waitForCleanup)
|
||||
public TestLifecycle(TestLog log, Configuration configuration, IWebCallTimeSet webCallTimeSet, IK8sTimeSet k8sTimeSet, string testNamespace, string testName, string deployId, bool waitForCleanup)
|
||||
{
|
||||
Log = log;
|
||||
Configuration = configuration;
|
||||
WebCallTimeSet = webCallTimeSet;
|
||||
K8STimeSet = k8sTimeSet;
|
||||
TestNamespace = testNamespace;
|
||||
this.testName = testName;
|
||||
TestStart = DateTime.UtcNow;
|
||||
|
||||
entryPoint = new EntryPoint(log, configuration.GetK8sConfiguration(k8sTimeSet, this, testNamespace), configuration.GetFileManagerFolder(), webCallTimeSet, k8sTimeSet);
|
||||
@ -36,6 +38,28 @@ namespace DistTestCore
|
||||
log.WriteLogTag();
|
||||
}
|
||||
|
||||
public void Start(ILifecycleComponentAccess access)
|
||||
{
|
||||
Log.Log($"*** Begin: {testName}");
|
||||
}
|
||||
|
||||
public void Stop(ILifecycleComponentAccess access, DistTestResult result)
|
||||
{
|
||||
Log.Log($"*** Finished: {testName} = {result.Status}");
|
||||
if (!string.IsNullOrEmpty(result.Result))
|
||||
{
|
||||
Log.Log(result.Result);
|
||||
Log.Log($"{result.Trace}");
|
||||
}
|
||||
|
||||
if (!result.Success)
|
||||
{
|
||||
DownloadAllLogs();
|
||||
}
|
||||
|
||||
DeleteAllResources();
|
||||
}
|
||||
|
||||
public DateTime TestStart { get; }
|
||||
public TestLog Log { get; }
|
||||
public Configuration Configuration { get; }
|
||||
@ -45,7 +69,7 @@ namespace DistTestCore
|
||||
public bool WaitForCleanup { get; }
|
||||
public CoreInterface CoreInterface { get; }
|
||||
|
||||
public void DeleteAllResources()
|
||||
private void DeleteAllResources()
|
||||
{
|
||||
entryPoint.Decommission(
|
||||
deleteKubernetesResources: true,
|
||||
|
||||
@ -4,46 +4,56 @@ using DistTestCore;
|
||||
|
||||
namespace CodexTests
|
||||
{
|
||||
public class AutoBootstrapDistTest : CodexDistTest
|
||||
public class AutoBootstrapComponent : ILifecycleComponent
|
||||
{
|
||||
private readonly Dictionary<TestLifecycle, ICodexNode> bootstrapNodes = new Dictionary<TestLifecycle, ICodexNode>();
|
||||
private bool isBooting = false;
|
||||
public ICodexNode? BootstrapNode { get; private set; } = null;
|
||||
|
||||
protected override void LifecycleStart(TestLifecycle tl)
|
||||
public void Start(ILifecycleComponentAccess access)
|
||||
{
|
||||
base.LifecycleStart(tl);
|
||||
if (!bootstrapNodes.ContainsKey(tl))
|
||||
{
|
||||
isBooting = true;
|
||||
bootstrapNodes.Add(tl, StartCodex(s => s.WithName("BOOTSTRAP_" + tl.TestNamespace)));
|
||||
isBooting = false;
|
||||
}
|
||||
if (BootstrapNode != null) return;
|
||||
|
||||
var tl = access.Get<TestLifecycle>();
|
||||
var ci = tl.CoreInterface;
|
||||
var testNamespace = tl.TestNamespace;
|
||||
|
||||
BootstrapNode = ci.StartCodexNode(s => s.WithName("BOOTSTRAP_" + testNamespace));
|
||||
}
|
||||
|
||||
protected override void LifecycleStop(TestLifecycle lifecycle, DistTestResult result)
|
||||
public void ApplyBootstrapNode(ICodexSetup setup)
|
||||
{
|
||||
bootstrapNodes.Remove(lifecycle);
|
||||
base.LifecycleStop(lifecycle, result);
|
||||
if (BootstrapNode == null) return;
|
||||
|
||||
setup.WithBootstrapNode(BootstrapNode);
|
||||
}
|
||||
|
||||
public void Stop(ILifecycleComponentAccess access, DistTestResult result)
|
||||
{
|
||||
if (BootstrapNode == null) return;
|
||||
BootstrapNode.Stop(waitTillStopped: false);
|
||||
}
|
||||
}
|
||||
|
||||
public class AutoBootstrapDistTest : CodexDistTest
|
||||
{
|
||||
|
||||
protected override void CreateComponents(ILifecycleComponentCollector collector)
|
||||
{
|
||||
base.CreateComponents(collector);
|
||||
collector.AddComponent(new AutoBootstrapComponent());
|
||||
}
|
||||
|
||||
protected override void OnCodexSetup(ICodexSetup setup)
|
||||
{
|
||||
if (isBooting) return;
|
||||
|
||||
var node = BootstrapNode;
|
||||
if (node != null) setup.WithBootstrapNode(node);
|
||||
Get<AutoBootstrapComponent>().ApplyBootstrapNode(setup);
|
||||
}
|
||||
|
||||
protected ICodexNode BootstrapNode
|
||||
{
|
||||
get
|
||||
{
|
||||
var tl = Get();
|
||||
if (bootstrapNodes.TryGetValue(tl, out var node))
|
||||
{
|
||||
return node;
|
||||
}
|
||||
throw new InvalidOperationException("Bootstrap node not yet started.");
|
||||
var bn = Get<AutoBootstrapComponent>().BootstrapNode;
|
||||
if (bn == null) throw new InvalidOperationException("BootstrapNode accessed before initialized.");
|
||||
return bn;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
using BlockchainUtils;
|
||||
using CodexClient;
|
||||
using CodexClient.Hooks;
|
||||
using CodexContractsPlugin;
|
||||
using CodexNetDeployer;
|
||||
using CodexPlugin;
|
||||
@ -17,86 +16,74 @@ using Newtonsoft.Json;
|
||||
using NUnit.Framework;
|
||||
using NUnit.Framework.Constraints;
|
||||
using OverwatchTranscript;
|
||||
using Utils;
|
||||
|
||||
namespace CodexTests
|
||||
{
|
||||
public class CodexLogTrackerProvider : ICodexHooksProvider
|
||||
public class CodexDistTestComponents : ILifecycleComponent
|
||||
{
|
||||
private readonly Action<ICodexNode> addNode;
|
||||
private readonly object nodesLock = new object();
|
||||
|
||||
public CodexLogTrackerProvider(Action<ICodexNode> addNode)
|
||||
public CodexDistTestComponents(CodexTranscriptWriter? writer)
|
||||
{
|
||||
this.addNode = addNode;
|
||||
Writer = writer;
|
||||
}
|
||||
|
||||
// See TestLifecycle.cs DownloadAllLogs()
|
||||
public ICodexNodeHooks CreateHooks(string nodeName)
|
||||
public CodexTranscriptWriter? Writer { get; }
|
||||
public BlockCache Cache { get; } = new();
|
||||
public List<ICodexNode> Nodes { get; } = new();
|
||||
|
||||
public void Start(ILifecycleComponentAccess access)
|
||||
{
|
||||
return new CodexLogTracker(addNode);
|
||||
var ci = access.Get<TestLifecycle>().CoreInterface;
|
||||
ci.AddCodexHooksProvider(new CodexLogTrackerProvider(n =>
|
||||
{
|
||||
lock (nodesLock)
|
||||
{
|
||||
Nodes.Add(n);
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
public class CodexLogTracker : ICodexNodeHooks
|
||||
public void Stop(ILifecycleComponentAccess access, DistTestResult result)
|
||||
{
|
||||
private readonly Action<ICodexNode> addNode;
|
||||
var tl = access.Get<TestLifecycle>();
|
||||
var log = tl.Log;
|
||||
var logFiles = tl.DownloadAllLogs();
|
||||
|
||||
public CodexLogTracker(Action<ICodexNode> addNode)
|
||||
TeardownTranscript(log, logFiles, result);
|
||||
|
||||
// todo: on not success: go to nodes and dl logs?
|
||||
// or fix disttest failure log download so we can always have logs even for non-codexes?
|
||||
}
|
||||
|
||||
private void TeardownTranscript(TestLog log, IDownloadedLog[] logFiles, DistTestResult result)
|
||||
{
|
||||
if (Writer == null) return;
|
||||
|
||||
Writer.AddResult(result.Success, result.Result);
|
||||
|
||||
try
|
||||
{
|
||||
this.addNode = addNode;
|
||||
Stopwatch.Measure(log, "Transcript.ProcessLogs", () =>
|
||||
{
|
||||
Writer.ProcessLogs(logFiles);
|
||||
});
|
||||
|
||||
Stopwatch.Measure(log, $"Transcript.Finalize", () =>
|
||||
{
|
||||
Writer.IncludeFile(log.GetFullName());
|
||||
Writer.Finalize();
|
||||
});
|
||||
}
|
||||
|
||||
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)
|
||||
catch (Exception ex)
|
||||
{
|
||||
log.Error("Failure during transcript teardown: " + ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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>>();
|
||||
|
||||
public CodexDistTest()
|
||||
{
|
||||
ProjectPlugin.Load<CodexPlugin.CodexPlugin>();
|
||||
@ -112,34 +99,12 @@ namespace CodexTests
|
||||
localBuilder.Build();
|
||||
}
|
||||
|
||||
protected override void LifecycleStart(TestLifecycle lifecycle)
|
||||
protected override void CreateComponents(ILifecycleComponentCollector collector)
|
||||
{
|
||||
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();
|
||||
}
|
||||
}
|
||||
base.CreateComponents(collector);
|
||||
collector.AddComponent(new CodexDistTestComponents(
|
||||
SetupTranscript()
|
||||
));
|
||||
}
|
||||
|
||||
public ICodexNode StartCodex()
|
||||
@ -173,6 +138,11 @@ namespace CodexTests
|
||||
return Ci.StartGethNode(GetBlockCache(), setup);
|
||||
}
|
||||
|
||||
private BlockCache GetBlockCache()
|
||||
{
|
||||
return Get<CodexDistTestComponents>().Cache;
|
||||
}
|
||||
|
||||
public PeerConnectionTestHelpers CreatePeerConnectionTestHelpers()
|
||||
{
|
||||
return new PeerConnectionTestHelpers(GetTestLog());
|
||||
@ -180,7 +150,7 @@ namespace CodexTests
|
||||
|
||||
public PeerDownloadTestHelpers CreatePeerDownloadTestHelpers()
|
||||
{
|
||||
return new PeerDownloadTestHelpers(GetTestLog(), Get().GetFileManager());
|
||||
return new PeerDownloadTestHelpers(GetTestLog(), Get<TestLifecycle>().GetFileManager());
|
||||
}
|
||||
|
||||
public void AssertBalance(ICodexContracts contracts, ICodexNode codexNode, Constraint constraint, string msg = "")
|
||||
@ -258,81 +228,20 @@ 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);
|
||||
}
|
||||
}
|
||||
|
||||
private void TeardownTranscript(TestLifecycle lifecycle, DistTestResult result)
|
||||
{
|
||||
var attr = GetTranscriptAttributeOfCurrentTest();
|
||||
if (attr == null) return;
|
||||
|
||||
var outputFilepath = GetOutputFullPath(lifecycle, attr);
|
||||
|
||||
CodexTranscriptWriter writer = null!;
|
||||
lock (_lock)
|
||||
{
|
||||
writer = writers[lifecycle];
|
||||
writers.Remove(lifecycle);
|
||||
}
|
||||
|
||||
writer.AddResult(result.Success, result.Result);
|
||||
|
||||
try
|
||||
{
|
||||
Stopwatch.Measure(lifecycle.Log, "Transcript.ProcessLogs", () =>
|
||||
{
|
||||
writer.ProcessLogs(lifecycle.DownloadAllLogs());
|
||||
});
|
||||
|
||||
Stopwatch.Measure(lifecycle.Log, $"Transcript.Finalize: {outputFilepath}", () =>
|
||||
{
|
||||
writer.IncludeFile(lifecycle.Log.GetFullName());
|
||||
writer.Finalize(outputFilepath);
|
||||
});
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
lifecycle.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];
|
||||
return writer;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
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)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,64 +1,64 @@
|
||||
using NUnit.Framework;
|
||||
//using NUnit.Framework;
|
||||
|
||||
namespace FrameworkTests
|
||||
{
|
||||
[Parallelizable(ParallelScope.All)]
|
||||
[TestFixture(10)]
|
||||
[TestFixture(20)]
|
||||
[TestFixture(30)]
|
||||
public class LifecycelyTest
|
||||
{
|
||||
public LifecycelyTest(int num)
|
||||
{
|
||||
Log("ctor", GetCurrentTestName(), num);
|
||||
this.num = num;
|
||||
}
|
||||
//namespace FrameworkTests
|
||||
//{
|
||||
// [Parallelizable(ParallelScope.All)]
|
||||
// [TestFixture(10)]
|
||||
// [TestFixture(20)]
|
||||
// [TestFixture(30)]
|
||||
// public class LifecycelyTest
|
||||
// {
|
||||
// public LifecycelyTest(int num)
|
||||
// {
|
||||
// Log("ctor", GetCurrentTestName(), num);
|
||||
// this.num = num;
|
||||
// }
|
||||
|
||||
[SetUp]
|
||||
public void Setup()
|
||||
{
|
||||
Log(nameof(Setup), GetCurrentTestName());
|
||||
}
|
||||
// [SetUp]
|
||||
// public void Setup()
|
||||
// {
|
||||
// Log(nameof(Setup), GetCurrentTestName());
|
||||
// }
|
||||
|
||||
[TearDown]
|
||||
public void TearDown()
|
||||
{
|
||||
Log(nameof(TearDown), GetCurrentTestName());
|
||||
}
|
||||
// [TearDown]
|
||||
// public void TearDown()
|
||||
// {
|
||||
// Log(nameof(TearDown), GetCurrentTestName());
|
||||
// }
|
||||
|
||||
[Test]
|
||||
public void A()
|
||||
{
|
||||
Log(nameof(A), "Run");
|
||||
SleepRandom();
|
||||
Log(nameof(A), "Finish");
|
||||
}
|
||||
// [Test]
|
||||
// public void A()
|
||||
// {
|
||||
// Log(nameof(A), "Run");
|
||||
// SleepRandom();
|
||||
// Log(nameof(A), "Finish");
|
||||
// }
|
||||
|
||||
[Test]
|
||||
public void B()
|
||||
{
|
||||
Log(nameof(B), "Run");
|
||||
SleepRandom();
|
||||
Log(nameof(B), "Finish");
|
||||
}
|
||||
// [Test]
|
||||
// public void B()
|
||||
// {
|
||||
// Log(nameof(B), "Run");
|
||||
// SleepRandom();
|
||||
// Log(nameof(B), "Finish");
|
||||
// }
|
||||
|
||||
[Test]
|
||||
public void C()
|
||||
{
|
||||
Log(nameof(C), "Run");
|
||||
SleepRandom();
|
||||
Log(nameof(C), "Finish");
|
||||
}
|
||||
// [Test]
|
||||
// public void C()
|
||||
// {
|
||||
// Log(nameof(C), "Run");
|
||||
// SleepRandom();
|
||||
// Log(nameof(C), "Finish");
|
||||
// }
|
||||
|
||||
[Test]
|
||||
[Combinatorial]
|
||||
public void Multi(
|
||||
[Values(1, 2, 3)] int num)
|
||||
{
|
||||
Log(nameof(Multi), "Run", num);
|
||||
SleepRandom();
|
||||
Log(nameof(Multi), "Finish", num);
|
||||
}
|
||||
// [Test]
|
||||
// [Combinatorial]
|
||||
// public void Multi(
|
||||
// [Values(1, 2, 3)] int num)
|
||||
// {
|
||||
// Log(nameof(Multi), "Run", num);
|
||||
// SleepRandom();
|
||||
// Log(nameof(Multi), "Finish", num);
|
||||
// }
|
||||
|
||||
|
||||
|
||||
@ -71,46 +71,46 @@ namespace FrameworkTests
|
||||
|
||||
|
||||
|
||||
private static readonly Random r = new Random();
|
||||
private readonly int num;
|
||||
// private static readonly Random r = new Random();
|
||||
// private readonly int num;
|
||||
|
||||
private void SleepRandom()
|
||||
{
|
||||
Thread.Sleep(TimeSpan.FromSeconds(5.0));
|
||||
Thread.Sleep(TimeSpan.FromMilliseconds(r.Next(100, 1000)));
|
||||
}
|
||||
// private void SleepRandom()
|
||||
// {
|
||||
// Thread.Sleep(TimeSpan.FromSeconds(5.0));
|
||||
// Thread.Sleep(TimeSpan.FromMilliseconds(r.Next(100, 1000)));
|
||||
// }
|
||||
|
||||
private void Log(string scope, string msg)
|
||||
{
|
||||
ALog.Log($"{num} {scope} {msg}");
|
||||
}
|
||||
// private void Log(string scope, string msg)
|
||||
// {
|
||||
// ALog.Log($"{num} {scope} {msg}");
|
||||
// }
|
||||
|
||||
private void Log(string scope, string msg, int num)
|
||||
{
|
||||
ALog.Log($"{this.num} {scope} {msg} {num}");
|
||||
}
|
||||
// private void Log(string scope, string msg, int num)
|
||||
// {
|
||||
// ALog.Log($"{this.num} {scope} {msg} {num}");
|
||||
// }
|
||||
|
||||
private string GetCurrentTestName()
|
||||
{
|
||||
return $"[{TestContext.CurrentContext.Test.Name}]";
|
||||
}
|
||||
}
|
||||
// private string GetCurrentTestName()
|
||||
// {
|
||||
// return $"[{TestContext.CurrentContext.Test.Name}]";
|
||||
// }
|
||||
// }
|
||||
|
||||
|
||||
|
||||
|
||||
public class ALog
|
||||
{
|
||||
private static readonly object _lock = new object();
|
||||
// public class ALog
|
||||
// {
|
||||
// private static readonly object _lock = new object();
|
||||
|
||||
public static void Log(string msg)
|
||||
{
|
||||
lock (_lock)
|
||||
{
|
||||
File.AppendAllLines("C:\\Users\\vexor\\Desktop\\Alog.txt", [msg]);
|
||||
}
|
||||
}
|
||||
}
|
||||
// public static void Log(string msg)
|
||||
// {
|
||||
// lock (_lock)
|
||||
// {
|
||||
// File.AppendAllLines("C:\\Users\\vexor\\Desktop\\Alog.txt", [msg]);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
|
||||
|
||||
@ -122,105 +122,99 @@ namespace FrameworkTests
|
||||
|
||||
|
||||
|
||||
public interface ITestLifecycleComponent
|
||||
{
|
||||
void Start();
|
||||
void Stop(string results);
|
||||
}
|
||||
|
||||
// public class Base
|
||||
// {
|
||||
// private readonly Dictionary<int, Dictionary<Type, ITestLifecycleComponent>> anyFields = new();
|
||||
|
||||
public class Base
|
||||
{
|
||||
private readonly Dictionary<int, Dictionary<Type, ITestLifecycleComponent>> anyFields = new();
|
||||
// public void Setup()
|
||||
// {
|
||||
// var testId = 23;
|
||||
|
||||
public void Setup()
|
||||
{
|
||||
var testId = 23;
|
||||
// var fields = new Dictionary<Type, ITestLifecycleComponent>();
|
||||
// anyFields.Add(testId, fields);
|
||||
// YieldFields(field =>
|
||||
// {
|
||||
// fields.Add(field.GetType(), field);
|
||||
// });
|
||||
|
||||
var fields = new Dictionary<Type, ITestLifecycleComponent>();
|
||||
anyFields.Add(testId, fields);
|
||||
YieldFields(field =>
|
||||
{
|
||||
fields.Add(field.GetType(), field);
|
||||
});
|
||||
// foreach (var field in fields.Values)
|
||||
// {
|
||||
// field.Start();
|
||||
// }
|
||||
// }
|
||||
|
||||
foreach (var field in fields.Values)
|
||||
{
|
||||
field.Start();
|
||||
}
|
||||
}
|
||||
// public void TearDown()
|
||||
// {
|
||||
// var testId = 23;
|
||||
|
||||
public void TearDown()
|
||||
{
|
||||
var testId = 23;
|
||||
// // foreach stop
|
||||
|
||||
// foreach stop
|
||||
// anyFields.Remove(testId);
|
||||
// }
|
||||
|
||||
anyFields.Remove(testId);
|
||||
}
|
||||
// public T Get<T>()
|
||||
// {
|
||||
// int testId = 123;
|
||||
// var fields = anyFields[testId];
|
||||
// var type = typeof(T);
|
||||
// var result = fields[type];
|
||||
// return (T)result;
|
||||
// }
|
||||
|
||||
public T Get<T>()
|
||||
{
|
||||
int testId = 123;
|
||||
var fields = anyFields[testId];
|
||||
var type = typeof(T);
|
||||
var result = fields[type];
|
||||
return (T)result;
|
||||
}
|
||||
// public BaseFields GetBaseField()
|
||||
// {
|
||||
// return Get<BaseFields>();
|
||||
// }
|
||||
|
||||
public BaseFields GetBaseField()
|
||||
{
|
||||
return Get<BaseFields>();
|
||||
}
|
||||
// protected virtual void YieldFields(Action<ITestLifecycleComponent> giveField)
|
||||
// {
|
||||
// giveField(new BaseFields());
|
||||
// }
|
||||
// }
|
||||
|
||||
protected virtual void YieldFields(Action<ITestLifecycleComponent> giveField)
|
||||
{
|
||||
giveField(new BaseFields());
|
||||
}
|
||||
}
|
||||
// public class Mid : Base
|
||||
// {
|
||||
// protected override void YieldFields(Action<ITestLifecycleComponent> giveField)
|
||||
// {
|
||||
// base.YieldFields(giveField);
|
||||
// giveField(new MidFields());
|
||||
// }
|
||||
|
||||
public class Mid : Base
|
||||
{
|
||||
protected override void YieldFields(Action<ITestLifecycleComponent> giveField)
|
||||
{
|
||||
base.YieldFields(giveField);
|
||||
giveField(new MidFields());
|
||||
}
|
||||
// public MidFields GetMid()
|
||||
// {
|
||||
// return Get<MidFields>();
|
||||
// }
|
||||
// }
|
||||
|
||||
public MidFields GetMid()
|
||||
{
|
||||
return Get<MidFields>();
|
||||
}
|
||||
}
|
||||
// public class Top : Mid
|
||||
// {
|
||||
// protected override void YieldFields(Action<ITestLifecycleComponent> giveField)
|
||||
// {
|
||||
// base.YieldFields(giveField);
|
||||
// giveField(new TopFields());
|
||||
// }
|
||||
|
||||
public class Top : Mid
|
||||
{
|
||||
protected override void YieldFields(Action<ITestLifecycleComponent> giveField)
|
||||
{
|
||||
base.YieldFields(giveField);
|
||||
giveField(new TopFields());
|
||||
}
|
||||
// public TopFields GetTop()
|
||||
// {
|
||||
// return Get<TopFields>();
|
||||
// }
|
||||
// }
|
||||
|
||||
public TopFields GetTop()
|
||||
{
|
||||
return Get<TopFields>();
|
||||
}
|
||||
}
|
||||
// public class BaseFields : ITestLifecycleComponent
|
||||
// {
|
||||
// public string EntryPoint { get; set; } = string.Empty;
|
||||
// public string Log { get; set; } = string.Empty;
|
||||
// }
|
||||
|
||||
public class BaseFields : ITestLifecycleComponent
|
||||
{
|
||||
public string EntryPoint { get; set; } = string.Empty;
|
||||
public string Log { get; set; } = string.Empty;
|
||||
}
|
||||
// public class MidFields : ITestLifecycleComponent
|
||||
// {
|
||||
// public string Nodes { get; set; } = string.Empty;
|
||||
// }
|
||||
|
||||
public class MidFields : ITestLifecycleComponent
|
||||
{
|
||||
public string Nodes { get; set; } = string.Empty;
|
||||
}
|
||||
|
||||
public class TopFields : ITestLifecycleComponent
|
||||
{
|
||||
public string Geth { get; set; } = string.Empty;
|
||||
public string Contracts { get; set; } = string.Empty;
|
||||
}
|
||||
}
|
||||
// public class TopFields : ITestLifecycleComponent
|
||||
// {
|
||||
// public string Geth { get; set; } = string.Empty;
|
||||
// public string Contracts { get; set; } = string.Empty;
|
||||
// }
|
||||
//}
|
||||
|
||||
6
Tests/FrameworkTests/Parallelism.cs
Normal file
6
Tests/FrameworkTests/Parallelism.cs
Normal file
@ -0,0 +1,6 @@
|
||||
using NUnit.Framework;
|
||||
|
||||
[assembly: LevelOfParallelism(100)]
|
||||
namespace FrameworkTests
|
||||
{
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user