diff --git a/Framework/Utils/Str.cs b/Framework/Utils/Str.cs index aea19ec8..ab8fe46d 100644 --- a/Framework/Utils/Str.cs +++ b/Framework/Utils/Str.cs @@ -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); } diff --git a/ProjectPlugins/CodexPlugin/OverwatchSupport/CodexTranscriptWriter.cs b/ProjectPlugins/CodexPlugin/OverwatchSupport/CodexTranscriptWriter.cs index afd8d1a2..95b8dde6 100644 --- a/ProjectPlugins/CodexPlugin/OverwatchSupport/CodexTranscriptWriter.cs +++ b/ProjectPlugins/CodexPlugin/OverwatchSupport/CodexTranscriptWriter.cs @@ -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, "'", "'"); diff --git a/ProjectPlugins/CodexPlugin/OverwatchSupport/CodexTranscriptWriterConfig.cs b/ProjectPlugins/CodexPlugin/OverwatchSupport/CodexTranscriptWriterConfig.cs index 247494c8..112f5b16 100644 --- a/ProjectPlugins/CodexPlugin/OverwatchSupport/CodexTranscriptWriterConfig.cs +++ b/ProjectPlugins/CodexPlugin/OverwatchSupport/CodexTranscriptWriterConfig.cs @@ -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; } } } diff --git a/Tests/CodexReleaseTests/MarketTests/MarketplaceAutoBootstrapDistTest.cs b/Tests/CodexReleaseTests/MarketTests/MarketplaceAutoBootstrapDistTest.cs index 49a3bcd5..f7d94473 100644 --- a/Tests/CodexReleaseTests/MarketTests/MarketplaceAutoBootstrapDistTest.cs +++ b/Tests/CodexReleaseTests/MarketTests/MarketplaceAutoBootstrapDistTest.cs @@ -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 handles = new Dictionary(); + 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() diff --git a/Tests/DistTestCore/DistTest.cs b/Tests/DistTestCore/DistTest.cs index 104bf8d8..4c6cb0af 100644 --- a/Tests/DistTestCore/DistTest.cs +++ b/Tests/DistTestCore/DistTest.cs @@ -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 lifecycles = new Dictionary(); - 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 options, string label = "") { - return Get().GenerateTestFile(options, label); + return lifecycle.GenerateTestFile(options, label); } /// @@ -137,12 +100,22 @@ namespace DistTestCore /// 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 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()) @@ -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(); diff --git a/Tests/DistTestCore/Global.cs b/Tests/DistTestCore/Global.cs new file mode 100644 index 00000000..4ba1374b --- /dev/null +++ b/Tests/DistTestCore/Global.cs @@ -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 + ); + } + } +} diff --git a/Tests/DistTestCore/Logs/FixtureLog.cs b/Tests/DistTestCore/Logs/FixtureLog.cs index 9d3c77d3..5978a602 100644 --- a/Tests/DistTestCore/Logs/FixtureLog.cs +++ b/Tests/DistTestCore/Logs/FixtureLog.cs @@ -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 = "") diff --git a/Tests/DistTestCore/Logs/TestLog.cs b/Tests/DistTestCore/Logs/TestLog.cs index 0dca1464..5c38f951 100644 --- a/Tests/DistTestCore/Logs/TestLog.cs +++ b/Tests/DistTestCore/Logs/TestLog.cs @@ -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); diff --git a/Tests/DistTestCore/NameUtils.cs b/Tests/DistTestCore/NameUtils.cs index 55489db9..44919d51 100644 --- a/Tests/DistTestCore/NameUtils.cs +++ b/Tests/DistTestCore/NameUtils.cs @@ -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'); diff --git a/Tests/ExperimentalTests/AutoBootstrapDistTest.cs b/Tests/ExperimentalTests/AutoBootstrapDistTest.cs index d8ac6805..93fcf6f7 100644 --- a/Tests/ExperimentalTests/AutoBootstrapDistTest.cs +++ b/Tests/ExperimentalTests/AutoBootstrapDistTest.cs @@ -1,29 +1,27 @@ using CodexClient; using CodexPlugin; -using DistTestCore; +using NUnit.Framework; namespace CodexTests { public class AutoBootstrapDistTest : CodexDistTest { - private readonly Dictionary bootstrapNodes = new Dictionary(); 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."); - } - } } } diff --git a/Tests/ExperimentalTests/CodexDistTest.cs b/Tests/ExperimentalTests/CodexDistTest.cs index d27216d3..422b5bd7 100644 --- a/Tests/ExperimentalTests/CodexDistTest.cs +++ b/Tests/ExperimentalTests/CodexDistTest.cs @@ -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 addNode; - - public CodexLogTrackerProvider(Action addNode) - { - this.addNode = addNode; - } - - // See TestLifecycle.cs DownloadAllLogs() - public ICodexNodeHooks CreateHooks(string nodeName) - { - return new CodexLogTracker(addNode); - } - - public class CodexLogTracker : ICodexNodeHooks - { - private readonly Action addNode; - - public CodexLogTracker(Action 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 writers = new Dictionary(); - private static readonly Dictionary blockCaches = new Dictionary(); - - // this entire structure is not good and needs to be destroyed at the earliest convenience: - private static readonly Dictionary> nodes = new Dictionary>(); + private readonly BlockCache blockCache = new BlockCache(); + private readonly List nodes = new List(); + private CodexTranscriptWriter? writer; public CodexDistTest() { @@ -105,41 +33,25 @@ namespace CodexTests ProjectPlugin.Load(); } + [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()); - 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 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)] diff --git a/Tests/ExperimentalTests/CodexLogTrackerProvider.cs b/Tests/ExperimentalTests/CodexLogTrackerProvider.cs new file mode 100644 index 00000000..1b2fdd66 --- /dev/null +++ b/Tests/ExperimentalTests/CodexLogTrackerProvider.cs @@ -0,0 +1,73 @@ +using CodexClient; +using CodexClient.Hooks; +using Utils; + +namespace CodexTests +{ + public class CodexLogTrackerProvider : ICodexHooksProvider + { + private readonly Action addNode; + + public CodexLogTrackerProvider(Action addNode) + { + this.addNode = addNode; + } + + // See TestLifecycle.cs DownloadAllLogs() + public ICodexNodeHooks CreateHooks(string nodeName) + { + return new CodexLogTracker(addNode); + } + + public class CodexLogTracker : ICodexNodeHooks + { + private readonly Action addNode; + + public CodexLogTracker(Action 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) + { + } + } + } +}