diff --git a/CodexDistTestCore/CodexNodeGroup.cs b/CodexDistTestCore/CodexNodeGroup.cs index 8d8fda5..975eccf 100644 --- a/CodexDistTestCore/CodexNodeGroup.cs +++ b/CodexDistTestCore/CodexNodeGroup.cs @@ -1,4 +1,5 @@ -using k8s.Models; +using CodexDistTestCore.Config; +using k8s.Models; using System.Collections; namespace CodexDistTestCore @@ -11,10 +12,12 @@ namespace CodexDistTestCore public class CodexNodeGroup : ICodexNodeGroup { + private readonly TestLog log; private readonly IK8sManager k8SManager; - public CodexNodeGroup(int orderNumber, OfflineCodexNodes origin, IK8sManager k8SManager, OnlineCodexNode[] nodes) + public CodexNodeGroup(TestLog log, int orderNumber, OfflineCodexNodes origin, IK8sManager k8SManager, OnlineCodexNode[] nodes) { + this.log = log; OrderNumber = orderNumber; Origin = origin; this.k8SManager = k8SManager; @@ -63,7 +66,7 @@ namespace CodexDistTestCore return new V1ObjectMeta { Name = "codex-test-entrypoint-" + OrderNumber, - NamespaceProperty = K8sOperations.K8sNamespace + NamespaceProperty = K8sCluster.K8sNamespace }; } @@ -72,10 +75,17 @@ namespace CodexDistTestCore return new V1ObjectMeta { Name = "codex-test-node-" + OrderNumber, - NamespaceProperty = K8sOperations.K8sNamespace + NamespaceProperty = K8sCluster.K8sNamespace }; } + public CodexNodeLog DownloadLog(IOnlineCodexNode node) + { + var logDownloader = new PodLogDownloader(log, k8SManager); + var n = (OnlineCodexNode)node; + return logDownloader.DownloadLog(n); + } + public Dictionary GetSelector() { return new Dictionary { { "codex-test-node", "dist-test-" + OrderNumber } }; diff --git a/CodexDistTestCore/CodexNodeLog.cs b/CodexDistTestCore/CodexNodeLog.cs new file mode 100644 index 0000000..b4cae47 --- /dev/null +++ b/CodexDistTestCore/CodexNodeLog.cs @@ -0,0 +1,29 @@ +using NUnit.Framework; + +namespace CodexDistTestCore +{ + public class CodexNodeLog + { + private readonly LogFile logFile; + + public CodexNodeLog(LogFile logFile) + { + this.logFile = logFile; + } + + public void AssertLogContains(string expectedString) + { + using var file = File.OpenRead(logFile.FullFilename); + using var streamReader = new StreamReader(file); + + var line = streamReader.ReadLine(); + while (line != null) + { + if (line.Contains(expectedString)) return; + line = streamReader.ReadLine(); + } + + Assert.Fail($"Unable to find string '{expectedString}' in CodexNode log file {logFile.FilenameWithoutPath}"); + } + } +} diff --git a/CodexDistTestCore/CodexDockerImage.cs b/CodexDistTestCore/Config/CodexDockerImage.cs similarity index 98% rename from CodexDistTestCore/CodexDockerImage.cs rename to CodexDistTestCore/Config/CodexDockerImage.cs index a7dd353..7cd938e 100644 --- a/CodexDistTestCore/CodexDockerImage.cs +++ b/CodexDistTestCore/Config/CodexDockerImage.cs @@ -1,6 +1,6 @@ using k8s.Models; -namespace CodexDistTestCore +namespace CodexDistTestCore.Config { public class CodexDockerImage { diff --git a/CodexDistTestCore/Config/FileManagerConfig.cs b/CodexDistTestCore/Config/FileManagerConfig.cs new file mode 100644 index 0000000..f7befc2 --- /dev/null +++ b/CodexDistTestCore/Config/FileManagerConfig.cs @@ -0,0 +1,7 @@ +namespace CodexDistTestCore.Config +{ + public class FileManagerConfig + { + public const string Folder = "TestDataFiles"; + } +} diff --git a/CodexDistTestCore/Config/K8sCluster.cs b/CodexDistTestCore/Config/K8sCluster.cs new file mode 100644 index 0000000..0fd60d0 --- /dev/null +++ b/CodexDistTestCore/Config/K8sCluster.cs @@ -0,0 +1,39 @@ +using k8s; + +namespace CodexDistTestCore.Config +{ + public class K8sCluster + { + public const string K8sNamespace = "codex-test-namespace"; + private const string KubeConfigFile = "C:\\kube\\config"; + private readonly Dictionary K8sNodeLocationMap = new Dictionary + { + { Location.BensLaptop, "worker01" }, + { Location.BensOldGamingMachine, "worker02" }, + }; + + private KubernetesClientConfiguration? config; + + public KubernetesClientConfiguration GetK8sClientConfig() + { + if (config != null) return config; + config = KubernetesClientConfiguration.BuildConfigFromConfigFile(KubeConfigFile); + return config; + } + + public string GetIp() + { + var c = GetK8sClientConfig(); + + var host = c.Host.Replace("https://", ""); + + return host.Substring(0, host.IndexOf(':')); + } + + public string GetNodeLabelForLocation(Location location) + { + if (location == Location.Unspecified) return string.Empty; + return K8sNodeLocationMap[location]; + } + } +} diff --git a/CodexDistTestCore/Config/LogConfig.cs b/CodexDistTestCore/Config/LogConfig.cs new file mode 100644 index 0000000..a14470e --- /dev/null +++ b/CodexDistTestCore/Config/LogConfig.cs @@ -0,0 +1,7 @@ +namespace CodexDistTestCore.Config +{ + public class LogConfig + { + public const string LogRoot = "D:/CodexTestLogs"; + } +} diff --git a/CodexDistTestCore/DistTest.cs b/CodexDistTestCore/DistTest.cs index 55bd75c..1331c6a 100644 --- a/CodexDistTestCore/DistTest.cs +++ b/CodexDistTestCore/DistTest.cs @@ -1,4 +1,5 @@ -using NUnit.Framework; +using CodexDistTestCore.Config; +using NUnit.Framework; namespace CodexDistTestCore { @@ -41,7 +42,10 @@ namespace CodexDistTestCore } else { + var dockerImage = new CodexDockerImage(); log = new TestLog(); + log.Log($"Using docker image '{dockerImage.GetImageTag()}'"); + fileManager = new FileManager(log); k8sManager = new K8sManager(log, fileManager); } @@ -52,7 +56,8 @@ namespace CodexDistTestCore { try { - log.EndTest(k8sManager); + log.EndTest(); + IncludeLogsOnTestFailure(); k8sManager.DeleteAllResources(); fileManager.DeleteAllTestFiles(); } @@ -72,6 +77,39 @@ namespace CodexDistTestCore { return new OfflineCodexNodes(k8sManager, numberOfNodes); } + + private void IncludeLogsOnTestFailure() + { + var result = TestContext.CurrentContext.Result; + if (result.Outcome.Status == NUnit.Framework.Interfaces.TestStatus.Failed) + { + if (IsDownloadingLogsEnabled()) + { + log.Log("Downloading all CodexNode logs because of test failure..."); + k8sManager.ForEachOnlineGroup(DownloadLogs); + } + else + { + log.Log("Skipping download of all CodexNode logs due to [DontDownloadLogsOnFailure] attribute."); + } + } + } + + private void DownloadLogs(CodexNodeGroup group) + { + foreach (var node in group) + { + var downloader = new PodLogDownloader(log, k8sManager); + var n = (OnlineCodexNode)node; + downloader.DownloadLog(n); + } + } + + private bool IsDownloadingLogsEnabled() + { + var testProperties = TestContext.CurrentContext.Test.Properties; + return !testProperties.ContainsKey(PodLogDownloader.DontDownloadLogsOnFailureKey); + } } public static class GlobalTestFailure diff --git a/CodexDistTestCore/FileManager.cs b/CodexDistTestCore/FileManager.cs index f884b0a..6a2daf7 100644 --- a/CodexDistTestCore/FileManager.cs +++ b/CodexDistTestCore/FileManager.cs @@ -1,4 +1,5 @@ -using NUnit.Framework; +using CodexDistTestCore.Config; +using NUnit.Framework; namespace CodexDistTestCore { @@ -12,20 +13,19 @@ namespace CodexDistTestCore public class FileManager : IFileManager { public const int ChunkSize = 1024 * 1024; - private const string Folder = "TestDataFiles"; private readonly Random random = new Random(); private readonly List activeFiles = new List(); private readonly TestLog log; public FileManager(TestLog log) { - if (!Directory.Exists(Folder)) Directory.CreateDirectory(Folder); + if (!Directory.Exists(FileManagerConfig.Folder)) Directory.CreateDirectory(FileManagerConfig.Folder); this.log = log; } public TestFile CreateEmptyTestFile() { - var result = new TestFile(Path.Combine(Folder, Guid.NewGuid().ToString() + "_test.bin")); + var result = new TestFile(Path.Combine(FileManagerConfig.Folder, Guid.NewGuid().ToString() + "_test.bin")); File.Create(result.Filename).Close(); activeFiles.Add(result); return result; diff --git a/CodexDistTestCore/K8sManager.cs b/CodexDistTestCore/K8sManager.cs index 3530c96..22ec144 100644 --- a/CodexDistTestCore/K8sManager.cs +++ b/CodexDistTestCore/K8sManager.cs @@ -4,12 +4,13 @@ { ICodexNodeGroup BringOnline(OfflineCodexNodes node); IOfflineCodexNodes BringOffline(ICodexNodeGroup node); + void FetchPodLog(OnlineCodexNode node, IPodLogHandler logHandler); } public class K8sManager : IK8sManager { private readonly CodexGroupNumberSource codexGroupNumberSource = new CodexGroupNumberSource(); - private readonly List onlineCodexNodes = new List(); + private readonly List onlineCodexNodeGroups = new List(); private readonly KnownK8sPods knownPods = new KnownK8sPods(); private readonly TestLog log; private readonly IFileManager fileManager; @@ -47,17 +48,22 @@ K8s(k => k.DeleteAllResources()); } - public void FetchAllPodsLogs(IPodLogsHandler logHandler) + public void ForEachOnlineGroup(Action action) { - K8s(k => k.FetchAllPodsLogs(onlineCodexNodes.ToArray(), logHandler)); + foreach (var group in onlineCodexNodeGroups) action(group); + } + + public void FetchPodLog(OnlineCodexNode node, IPodLogHandler logHandler) + { + K8s(k => k.FetchPodLog(node, logHandler)); } private CodexNodeGroup CreateOnlineCodexNodes(OfflineCodexNodes offline) { var containers = CreateContainers(offline.NumberOfNodes); var online = containers.Select(c => new OnlineCodexNode(log, fileManager, c)).ToArray(); - var result = new CodexNodeGroup(codexGroupNumberSource.GetNextCodexNodeGroupNumber(), offline, this, online); - onlineCodexNodes.Add(result); + var result = new CodexNodeGroup(log, codexGroupNumberSource.GetNextCodexNodeGroupNumber(), offline, this, online); + onlineCodexNodeGroups.Add(result); return result; } @@ -72,7 +78,7 @@ private CodexNodeGroup GetAndRemoveActiveNodeFor(ICodexNodeGroup node) { var n = (CodexNodeGroup)node; - onlineCodexNodes.Remove(n); + onlineCodexNodeGroups.Remove(n); return n; } diff --git a/CodexDistTestCore/K8sOperations.cs b/CodexDistTestCore/K8sOperations.cs index f9054b8..a9f1613 100644 --- a/CodexDistTestCore/K8sOperations.cs +++ b/CodexDistTestCore/K8sOperations.cs @@ -1,4 +1,5 @@ -using k8s; +using CodexDistTestCore.Config; +using k8s; using k8s.Models; using NUnit.Framework; @@ -6,9 +7,8 @@ namespace CodexDistTestCore { public class K8sOperations { - public const string K8sNamespace = "codex-test-namespace"; - private readonly CodexDockerImage dockerImage = new CodexDockerImage(); + private readonly K8sCluster k8sCluster = new K8sCluster(); private readonly Kubernetes client; private readonly KnownK8sPods knownPods; @@ -16,9 +16,7 @@ namespace CodexDistTestCore { this.knownPods = knownPods; - // todo: If the default KubeConfig file does not suffice, change it here: - var config = KubernetesClientConfiguration.BuildConfigFromConfigFile(); - client = new Kubernetes(config); + client = new Kubernetes(k8sCluster.GetK8sClientConfig()); } public void Close() @@ -53,25 +51,10 @@ namespace CodexDistTestCore WaitUntilNamespaceDeleted(); } - public void FetchAllPodsLogs(CodexNodeGroup[] onlines, IPodLogsHandler logHandler) + public void FetchPodLog(OnlineCodexNode node, IPodLogHandler logHandler) { - var logNumberSource = new NumberSource(0); - foreach (var online in onlines) - { - foreach (var node in online) - { - WritePodLogs(online, node, logHandler, logNumberSource); - } - } - } - - private void WritePodLogs(CodexNodeGroup online, IOnlineCodexNode node, IPodLogsHandler logHandler, NumberSource logNumberSource) - { - var n = (OnlineCodexNode)node; - var nodeDescription = $"{online.Describe()} contains {n.GetName()}"; - - var stream = client.ReadNamespacedPodLog(online.PodInfo!.Name, K8sNamespace, n.Container.Name); - logHandler.Log(logNumberSource.GetNextNumber(), nodeDescription, stream); + var stream = client.ReadNamespacedPodLog(node.Group.PodInfo!.Name, K8sNamespace, node.Container.Name); + logHandler.Log(stream); } private void FetchPodInfo(CodexNodeGroup online) @@ -208,6 +191,7 @@ namespace CodexDistTestCore }, Spec = new V1PodSpec { + NodeSelector = CreateNodeSelector(offline), Containers = CreateDeploymentContainers(online, offline) } } @@ -217,6 +201,16 @@ namespace CodexDistTestCore online.Deployment = client.CreateNamespacedDeployment(deploymentSpec, K8sNamespace); } + private IDictionary CreateNodeSelector(OfflineCodexNodes offline) + { + if (offline.Location == Location.Unspecified) return new Dictionary(); + + return new Dictionary + { + { "codex-test-location", k8sCluster.GetNodeLabelForLocation(offline.Location) } + }; + } + private List CreateDeploymentContainers(CodexNodeGroup online, OfflineCodexNodes offline) { var result = new List(); @@ -276,6 +270,11 @@ namespace CodexDistTestCore } } + private string K8sNamespace + { + get { return K8sCluster.K8sNamespace; } + } + #endregion private bool IsTestNamespaceOnline() diff --git a/CodexDistTestCore/OfflineCodexNodes.cs b/CodexDistTestCore/OfflineCodexNodes.cs index 1b820e2..9092618 100644 --- a/CodexDistTestCore/OfflineCodexNodes.cs +++ b/CodexDistTestCore/OfflineCodexNodes.cs @@ -2,6 +2,7 @@ { public interface IOfflineCodexNodes { + IOfflineCodexNodes At(Location location); IOfflineCodexNodes WithLogLevel(CodexLogLevel level); IOfflineCodexNodes WithBootstrapNode(IOnlineCodexNode node); IOfflineCodexNodes WithStorageQuota(ByteSize storageQuota); @@ -17,11 +18,19 @@ Error } + public enum Location + { + Unspecified, + BensLaptop, + BensOldGamingMachine, + } + public class OfflineCodexNodes : IOfflineCodexNodes { private readonly IK8sManager k8SManager; public int NumberOfNodes { get; } + public Location Location { get; private set; } public CodexLogLevel? LogLevel { get; private set; } public IOnlineCodexNode? BootstrapNode { get; private set; } public ByteSize? StorageQuota { get; private set; } @@ -30,6 +39,7 @@ { this.k8SManager = k8SManager; NumberOfNodes = numberOfNodes; + Location = Location.Unspecified; } public ICodexNodeGroup BringOnline() @@ -37,6 +47,12 @@ return k8SManager.BringOnline(this); } + public IOfflineCodexNodes At(Location location) + { + Location = location; + return this; + } + public IOfflineCodexNodes WithBootstrapNode(IOnlineCodexNode node) { BootstrapNode = node; diff --git a/CodexDistTestCore/OnlineCodexNode.cs b/CodexDistTestCore/OnlineCodexNode.cs index d783656..f8cf90f 100644 --- a/CodexDistTestCore/OnlineCodexNode.cs +++ b/CodexDistTestCore/OnlineCodexNode.cs @@ -1,4 +1,5 @@ -using NUnit.Framework; +using CodexDistTestCore.Config; +using NUnit.Framework; namespace CodexDistTestCore { @@ -8,6 +9,7 @@ namespace CodexDistTestCore ContentId UploadFile(TestFile file); TestFile? DownloadContent(ContentId contentId); void ConnectToPeer(IOnlineCodexNode node); + CodexNodeLog DownloadLog(); } public class OnlineCodexNode : IOnlineCodexNode @@ -15,6 +17,7 @@ namespace CodexDistTestCore private const string SuccessfullyConnectedMessage = "Successfully connected to peer"; private const string UploadFailedMessage = "Unable to store block"; + private readonly K8sCluster k8sCluster = new K8sCluster(); private readonly TestLog log; private readonly IFileManager fileManager; @@ -77,6 +80,16 @@ namespace CodexDistTestCore Log($"Successfully connected to peer {peer.GetName()}."); } + public CodexNodeLog DownloadLog() + { + return Group.DownloadLog(this); + } + + public string Describe() + { + return $"{Group.Describe()} contains {GetName()}"; + } + private string GetPeerMultiAddress(OnlineCodexNode peer, CodexDebugResponse peerInfo) { var multiAddress = peerInfo.addrs.First(); @@ -101,7 +114,7 @@ namespace CodexDistTestCore private Http Http() { - return new Http(ip: "127.0.0.1", port: Container.ServicePort, baseUrl: "/api/codex/v1"); + return new Http(ip: k8sCluster.GetIp(), port: Container.ServicePort, baseUrl: "/api/codex/v1"); } private void Log(string msg) diff --git a/CodexDistTestCore/PodLogDownloader.cs b/CodexDistTestCore/PodLogDownloader.cs new file mode 100644 index 0000000..ce379d7 --- /dev/null +++ b/CodexDistTestCore/PodLogDownloader.cs @@ -0,0 +1,73 @@ +using NUnit.Framework; + +namespace CodexDistTestCore +{ + public interface IPodLogHandler + { + void Log(Stream log); + } + + [AttributeUsage(AttributeTargets.Method, AllowMultiple = false)] + public class DontDownloadLogsOnFailureAttribute : PropertyAttribute + { + public DontDownloadLogsOnFailureAttribute() + : base(Timing.UseLongTimeoutsKey) + { + } + } + + public class PodLogDownloader + { + public const string DontDownloadLogsOnFailureKey = "DontDownloadLogsOnFailure"; + + private readonly TestLog log; + private readonly IK8sManager k8SManager; + + public PodLogDownloader(TestLog log, IK8sManager k8sManager) + { + this.log = log; + k8SManager = k8sManager; + } + + public CodexNodeLog DownloadLog(OnlineCodexNode node) + { + var description = node.Describe(); + var subFile = log.CreateSubfile(); + + log.Log($"Downloading logs for {description} to file {subFile.FilenameWithoutPath}"); + var handler = new PodLogDownloadHandler(description, subFile); + k8SManager.FetchPodLog(node, handler); + return handler.CreateCodexNodeLog(); + } + } + + public class PodLogDownloadHandler : IPodLogHandler + { + private readonly string description; + private readonly LogFile log; + + public PodLogDownloadHandler(string description, LogFile log) + { + this.description = description; + this.log = log; + } + + public CodexNodeLog CreateCodexNodeLog() + { + return new CodexNodeLog(log); + } + + public void Log(Stream stream) + { + log.Write($"{description} -->> {log.FilenameWithoutPath}"); + log.WriteRaw(description); + var reader = new StreamReader(stream); + var line = reader.ReadLine(); + while (line != null) + { + log.WriteRaw(line); + line = reader.ReadLine(); + } + } + } +} diff --git a/CodexDistTestCore/PodLogsHandler.cs b/CodexDistTestCore/PodLogsHandler.cs deleted file mode 100644 index d7898f5..0000000 --- a/CodexDistTestCore/PodLogsHandler.cs +++ /dev/null @@ -1,7 +0,0 @@ -namespace CodexDistTestCore -{ - public interface IPodLogsHandler - { - void Log(int id, string podDescription, Stream log); - } -} diff --git a/CodexDistTestCore/TestLog.cs b/CodexDistTestCore/TestLog.cs index 95aad2b..aca6f1b 100644 --- a/CodexDistTestCore/TestLog.cs +++ b/CodexDistTestCore/TestLog.cs @@ -1,16 +1,20 @@ -using NUnit.Framework; +using CodexDistTestCore.Config; +using NUnit.Framework; namespace CodexDistTestCore { public class TestLog { - public const string LogRoot = "D:/CodexTestLogs"; + private readonly NumberSource subfileNumberSource = new NumberSource(0); private readonly LogFile file; + private readonly DateTime now; public TestLog() { + now = DateTime.UtcNow; + var name = GetTestName(); - file = new LogFile(name); + file = new LogFile(now, name); Log($"Begin: {name}"); } @@ -25,26 +29,23 @@ namespace CodexDistTestCore Log($"[ERROR] {message}"); } - public void EndTest(K8sManager k8sManager) + public void EndTest() { var result = TestContext.CurrentContext.Result; Log($"Finished: {GetTestName()} = {result.Outcome.Status}"); - if (!string.IsNullOrEmpty(result.Message)) { Log(result.Message); - } - - if (result.Outcome.Status == NUnit.Framework.Interfaces.TestStatus.Failed) - { Log($"{result.StackTrace}"); - - var logWriter = new PodLogWriter(file); - logWriter.IncludeFullPodLogging(k8sManager); } } + public LogFile CreateSubfile() + { + return new LogFile(now, $"{GetTestName()}_{subfileNumberSource.GetNextNumber().ToString().PadLeft(6, '0')}"); + } + private static string GetTestName() { var test = TestContext.CurrentContext.Test; @@ -60,70 +61,36 @@ namespace CodexDistTestCore } } - public class PodLogWriter : IPodLogsHandler - { - private readonly LogFile file; - - public PodLogWriter(LogFile file) - { - this.file = file; - } - - public void IncludeFullPodLogging(K8sManager k8sManager) - { - file.Write("Full pod logging:"); - k8sManager.FetchAllPodsLogs(this); - } - - public void Log(int id, string podDescription, Stream log) - { - var logFile = id.ToString().PadLeft(6, '0'); - file.Write($"{podDescription} -->> {logFile}"); - LogRaw(podDescription, logFile); - var reader = new StreamReader(log); - var line = reader.ReadLine(); - while (line != null) - { - LogRaw(line, logFile); - line = reader.ReadLine(); - } - } - - private void LogRaw(string message, string filename) - { - file!.WriteRaw(message, filename); - } - } - public class LogFile { private readonly string filepath; - private readonly string filename; - public LogFile(string name) + public LogFile(DateTime now, string name) { - var now = DateTime.UtcNow; - filepath = Path.Join( - TestLog.LogRoot, + LogConfig.LogRoot, $"{now.Year}-{Pad(now.Month)}", Pad(now.Day)); Directory.CreateDirectory(filepath); - filename = Path.Combine(filepath, $"{Pad(now.Hour)}-{Pad(now.Minute)}-{Pad(now.Second)}Z_{name.Replace('.', '-')}"); + FilenameWithoutPath = $"{Pad(now.Hour)}-{Pad(now.Minute)}-{Pad(now.Second)}Z_{name.Replace('.', '-')}.log"; + FullFilename = Path.Combine(filepath, FilenameWithoutPath); } + public string FullFilename { get; } + public string FilenameWithoutPath { get; } + public void Write(string message) { WriteRaw($"{GetTimestamp()} {message}"); } - public void WriteRaw(string message, string subfile = "") + public void WriteRaw(string message) { try { - File.AppendAllLines(filename + subfile + ".log", new[] { message }); + File.AppendAllLines(FullFilename, new[] { message }); } catch (Exception ex) { diff --git a/Tests/BasicTests/SimpleTests.cs b/Tests/BasicTests/SimpleTests.cs index c052d64..01e671d 100644 --- a/Tests/BasicTests/SimpleTests.cs +++ b/Tests/BasicTests/SimpleTests.cs @@ -1,4 +1,5 @@ using CodexDistTestCore; +using CodexDistTestCore.Config; using NUnit.Framework; namespace Tests.BasicTests @@ -19,13 +20,20 @@ namespace Tests.BasicTests Assert.That(debugInfo.codex.revision, Is.EqualTo(dockerImage.GetExpectedImageRevision())); } + [Test, DontDownloadLogsOnFailure] + public void CanAccessLogs() + { + var node = SetupCodexNodes(1).BringOnline()[0]; + + var log = node.DownloadLog(); + + log.AssertLogContains("Started codex node"); + } + [Test] public void OneClientTest() { - var primary = SetupCodexNodes(1) - .WithLogLevel(CodexLogLevel.Trace) - .WithStorageQuota(2.MB()) - .BringOnline()[0]; + var primary = SetupCodexNodes(1).BringOnline()[0]; var testFile = GenerateTestFile(1.MB()); @@ -37,12 +45,9 @@ namespace Tests.BasicTests } [Test] - public void TwoClientOnePodTest() + public void TwoClientsOnePodTest() { - var group = SetupCodexNodes(2) - .WithLogLevel(CodexLogLevel.Trace) - .WithStorageQuota(2.MB()) - .BringOnline(); + var group = SetupCodexNodes(2).BringOnline(); var primary = group[0]; var secondary = group[1]; @@ -51,14 +56,24 @@ namespace Tests.BasicTests } [Test] - public void TwoClientTwoPodTest() + public void TwoClientsTwoPodsTest() + { + var primary = SetupCodexNodes(1).BringOnline()[0]; + + var secondary = SetupCodexNodes(1).BringOnline()[0]; + + PerformTwoClientTest(primary, secondary); + } + + [Test] + public void TwoClientsTwoLocationsTest() { var primary = SetupCodexNodes(1) - .WithStorageQuota(2.MB()) + .At(Location.BensLaptop) .BringOnline()[0]; var secondary = SetupCodexNodes(1) - .WithStorageQuota(2.MB()) + .At(Location.BensOldGamingMachine) .BringOnline()[0]; PerformTwoClientTest(primary, secondary);