Revert "while better the new plan is still a mess"

This reverts commit 2dfdfac2bb52e4ff919ee5f1b3986a839d71b0a2.

# Conflicts:
#	Tests/FrameworkTests/LifecycelyTest.cs
This commit is contained in:
ThatBen 2025-04-25 11:08:38 +02:00
parent 373f7826bf
commit ad1b756db9
No known key found for this signature in database
GPG Key ID: 62C543548433D43E
12 changed files with 297 additions and 391 deletions

View File

@ -23,27 +23,16 @@ namespace CodexPlugin.OverwatchSupport
converter = new CodexLogConverter(writer, config, identityMap);
}
public void Finalize()
public void Finalize(string outputFilepath)
{
log.Log("Finalizing Codex transcript...");
writer.AddHeader(CodexHeaderKey, CreateCodexHeader());
writer.Write(GetOutputFullPath());
writer.Write(outputFilepath);
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, "'", "'");

View File

@ -2,13 +2,11 @@
{
public class CodexTranscriptWriterConfig
{
public CodexTranscriptWriterConfig(string outputFilename, bool includeBlockReceivedEvents)
public CodexTranscriptWriterConfig(bool includeBlockReceivedEvents)
{
OutputFilename = outputFilename;
IncludeBlockReceivedEvents = includeBlockReceivedEvents;
}
public string OutputFilename { get; }
public bool IncludeBlockReceivedEvents { get; }
}
}

View File

@ -10,41 +10,18 @@ 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 MarketplaceTestComponent(geth, contracts));
handles.Add(lifecycle, new MarketplaceHandle(geth, contracts));
}
protected override void LifecycleStop(TestLifecycle lifecycle, DistTestResult result)
@ -346,5 +323,17 @@ 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; }
}
}
}

View File

@ -19,8 +19,9 @@ 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 DistTestLifecycleComponents lifecycleComponents = new DistTestLifecycleComponents();
private readonly Dictionary<string, TestLifecycle> lifecycles = new Dictionary<string, TestLifecycle>();
private readonly string deployId;
public DistTest()
@ -88,12 +89,7 @@ namespace DistTestCore
{
try
{
var testName = GetCurrentTestName();
fixtureLog.WriteLogTag();
Stopwatch.Measure(fixtureLog, $"Setup for {testName}", () =>
{
lifecycleComponents.Setup(testName, CreateComponents);
});
CreateNewTestLifecycle();
}
catch (Exception ex)
{
@ -108,7 +104,7 @@ namespace DistTestCore
{
try
{
Stopwatch.Measure(fixtureLog, $"Teardown for {GetCurrentTestName()}", DisposeTestLifecycle);
DisposeTestLifecycle();
}
catch (Exception ex)
{
@ -175,49 +171,80 @@ namespace DistTestCore
{
}
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 LifecycleStart(TestLifecycle lifecycle)
{
}
public T Get<T>() where T : ILifecycleComponent
protected virtual void LifecycleStop(TestLifecycle lifecycle, DistTestResult testResult)
{
return lifecycleComponents.Get<T>(GetCurrentTestName());
}
private TestLifecycle Get()
protected virtual void CollectStatusLogData(TestLifecycle lifecycle, Dictionary<string, string> data)
{
return Get<TestLifecycle>();
}
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 testName = GetCurrentTestName();
var results = GetTestResult();
var lifecycle = Get();
var testResult = GetTestResult();
var testDuration = lifecycle.GetTestDuration();
var data = lifecycle.GetPluginMetadata();
fixtureLog.Log($"{GetCurrentTestName()} = {results} ({testDuration})");
statusLog.ConcludeTest(results, testDuration, data);
CollectStatusLogData(lifecycle, data);
fixtureLog.Log($"{GetCurrentTestName()} = {testResult} ({testDuration})");
statusLog.ConcludeTest(testResult, testDuration, data);
Stopwatch.Measure(fixtureLog, $"Teardown for {GetCurrentTestName()}", () =>
{
WriteEndTestLog(lifecycle.Log);
lifecycleComponents.TearDown(testName, results);
IncludeLogsOnTestFailure(lifecycle);
LifecycleStop(lifecycle, testResult);
lifecycle.DeleteAllResources();
lifecycles.Remove(GetCurrentTestName());
});
}
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()
{
@ -269,6 +296,28 @@ 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}]";
@ -279,8 +328,7 @@ 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;
var trace = TestContext.CurrentContext.Result.StackTrace;
return new DistTestResult(success, status, result ?? string.Empty, trace ?? string.Empty);
return new DistTestResult(success, status, result ?? string.Empty);
}
private bool IsDownloadingLogsEnabled()
@ -291,18 +339,16 @@ namespace DistTestCore
public class DistTestResult
{
public DistTestResult(bool success, string status, string result, string trace)
public DistTestResult(bool success, string status, string result)
{
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()
{

View File

@ -1,97 +0,0 @@
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);
}
}
}
}

View File

@ -4,25 +4,26 @@ 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 = "")
{
var result = TestLog.Create(this, name);
result.Log(NameUtils.GetRawFixtureName());
return result;
return TestLog.Create(this, name);
}
public static FixtureLog Create(LogConfig config, DateTime start, string deployId, string name = "")
{
var fullName = NameUtils.GetFixtureFullName(config, start, name);
var log = CreateMainLog(fullName, name);
var result = new FixtureLog(log, deployId);
result.Log(NameUtils.GetRawFixtureName());
return result;
return new FixtureLog(log, deployId);
}
}
}

View File

@ -1,4 +1,5 @@
using Logging;
using System.Xml.Linq;
namespace DistTestCore.Logs
{
@ -7,6 +8,7 @@ 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 = "")

View File

@ -10,24 +10,22 @@ using WebUtils;
namespace DistTestCore
{
public class TestLifecycle : IK8sHooks, ILifecycleComponent
public class TestLifecycle : IK8sHooks
{
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 testName, string deployId, bool waitForCleanup)
public TestLifecycle(TestLog log, Configuration configuration, IWebCallTimeSet webCallTimeSet, IK8sTimeSet k8sTimeSet, string testNamespace, 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);
@ -38,28 +36,6 @@ 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; }
@ -69,7 +45,7 @@ namespace DistTestCore
public bool WaitForCleanup { get; }
public CoreInterface CoreInterface { get; }
private void DeleteAllResources()
public void DeleteAllResources()
{
entryPoint.Decommission(
deleteKubernetesResources: true,

View File

@ -4,56 +4,46 @@ using DistTestCore;
namespace CodexTests
{
public class AutoBootstrapComponent : ILifecycleComponent
{
public ICodexNode? BootstrapNode { get; private set; } = null;
public void Start(ILifecycleComponentAccess access)
{
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));
}
public void ApplyBootstrapNode(ICodexSetup setup)
{
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
{
private readonly Dictionary<TestLifecycle, ICodexNode> bootstrapNodes = new Dictionary<TestLifecycle, ICodexNode>();
private bool isBooting = false;
protected override void CreateComponents(ILifecycleComponentCollector collector)
protected override void LifecycleStart(TestLifecycle tl)
{
base.CreateComponents(collector);
collector.AddComponent(new AutoBootstrapComponent());
base.LifecycleStart(tl);
if (!bootstrapNodes.ContainsKey(tl))
{
isBooting = true;
bootstrapNodes.Add(tl, StartCodex(s => s.WithName("BOOTSTRAP_" + tl.TestNamespace)));
isBooting = false;
}
}
protected override void LifecycleStop(TestLifecycle lifecycle, DistTestResult result)
{
bootstrapNodes.Remove(lifecycle);
base.LifecycleStop(lifecycle, result);
}
protected override void OnCodexSetup(ICodexSetup setup)
{
Get<AutoBootstrapComponent>().ApplyBootstrapNode(setup);
if (isBooting) return;
var node = BootstrapNode;
if (node != null) setup.WithBootstrapNode(node);
}
protected ICodexNode BootstrapNode
{
get
{
var bn = Get<AutoBootstrapComponent>().BootstrapNode;
if (bn == null) throw new InvalidOperationException("BootstrapNode accessed before initialized.");
return bn;
var tl = Get();
if (bootstrapNodes.TryGetValue(tl, out var node))
{
return node;
}
throw new InvalidOperationException("Bootstrap node not yet started.");
}
}
}

View File

@ -1,5 +1,6 @@
using BlockchainUtils;
using CodexClient;
using CodexClient.Hooks;
using CodexContractsPlugin;
using CodexNetDeployer;
using CodexPlugin;
@ -16,74 +17,86 @@ using Newtonsoft.Json;
using NUnit.Framework;
using NUnit.Framework.Constraints;
using OverwatchTranscript;
using Utils;
namespace CodexTests
{
public class CodexDistTestComponents : ILifecycleComponent
public class CodexLogTrackerProvider : ICodexHooksProvider
{
private readonly object nodesLock = new object();
private readonly Action<ICodexNode> addNode;
public CodexDistTestComponents(CodexTranscriptWriter? writer)
public CodexLogTrackerProvider(Action<ICodexNode> addNode)
{
Writer = writer;
this.addNode = addNode;
}
public CodexTranscriptWriter? Writer { get; }
public BlockCache Cache { get; } = new();
public List<ICodexNode> Nodes { get; } = new();
public void Start(ILifecycleComponentAccess access)
// See TestLifecycle.cs DownloadAllLogs()
public ICodexNodeHooks CreateHooks(string nodeName)
{
var ci = access.Get<TestLifecycle>().CoreInterface;
ci.AddCodexHooksProvider(new CodexLogTrackerProvider(n =>
return new CodexLogTracker(addNode);
}
public class CodexLogTracker : ICodexNodeHooks
{
private readonly Action<ICodexNode> addNode;
public CodexLogTracker(Action<ICodexNode> addNode)
{
lock (nodesLock)
{
Nodes.Add(n);
}
}));
}
public void Stop(ILifecycleComponentAccess access, DistTestResult result)
{
var tl = access.Get<TestLifecycle>();
var log = tl.Log;
var logFiles = tl.DownloadAllLogs();
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
{
Stopwatch.Measure(log, "Transcript.ProcessLogs", () =>
{
Writer.ProcessLogs(logFiles);
});
Stopwatch.Measure(log, $"Transcript.Finalize", () =>
{
Writer.IncludeFile(log.GetFullName());
Writer.Finalize();
});
this.addNode = addNode;
}
catch (Exception ex)
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)
{
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>();
@ -99,12 +112,34 @@ namespace CodexTests
localBuilder.Build();
}
protected override void CreateComponents(ILifecycleComponentCollector collector)
protected override void LifecycleStart(TestLifecycle lifecycle)
{
base.CreateComponents(collector);
collector.AddComponent(new CodexDistTestComponents(
SetupTranscript()
));
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();
}
}
}
public ICodexNode StartCodex()
@ -138,11 +173,6 @@ namespace CodexTests
return Ci.StartGethNode(GetBlockCache(), setup);
}
private BlockCache GetBlockCache()
{
return Get<CodexDistTestComponents>().Cache;
}
public PeerConnectionTestHelpers CreatePeerConnectionTestHelpers()
{
return new PeerConnectionTestHelpers(GetTestLog());
@ -150,7 +180,7 @@ namespace CodexTests
public PeerDownloadTestHelpers CreatePeerDownloadTestHelpers()
{
return new PeerDownloadTestHelpers(GetTestLog(), Get<TestLifecycle>().GetFileManager());
return new PeerDownloadTestHelpers(GetTestLog(), Get().GetFileManager());
}
public void AssertBalance(ICodexContracts contracts, ICodexNode codexNode, Constraint constraint, string msg = "")
@ -228,20 +258,81 @@ namespace CodexTests
return null;
}
private CodexTranscriptWriter? SetupTranscript()
private void SetupTranscript(TestLifecycle lifecycle)
{
var attr = GetTranscriptAttributeOfCurrentTest();
if (attr == null) return null;
if (attr == null) return;
var config = new CodexTranscriptWriterConfig(
attr.OutputFilename,
attr.IncludeBlockReceivedEvents
);
var log = new LogPrefixer(GetTestLog(), "(Transcript) ");
var log = new LogPrefixer(lifecycle.Log, "(Transcript) ");
var writer = new CodexTranscriptWriter(log, config, Transcript.NewWriter(log));
Ci.AddCodexHooksProvider(writer);
return 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];
}
}

View File

@ -1,73 +0,0 @@
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)
{
}
}
}
}

View File

@ -1,6 +0,0 @@
using NUnit.Framework;
[assembly: LevelOfParallelism(100)]
namespace FrameworkTests
{
}