From d2d7f3dea5253e3e17a33e4d40ad6043f108cf6c Mon Sep 17 00:00:00 2001 From: benbierens Date: Wed, 7 Jun 2023 08:30:10 +0200 Subject: [PATCH] Logging upload/download times and adds performance threshold assertions to large-file tests. --- DistTestCore/ByteSize.cs | 5 +++ DistTestCore/Codex/CodexContainerRecipe.cs | 4 ++ DistTestCore/DistTest.cs | 1 - .../Helpers/PeerDownloadTestHelpers.cs | 15 ++++--- DistTestCore/OnlineCodexNode.cs | 14 +++++-- Logging/Stopwatch.cs | 8 ++++ LongTests/BasicTests/DownloadTests.cs | 19 --------- LongTests/BasicTests/LargeFileTests.cs | 39 +++++++++++++++---- LongTests/Parallelism.cs | 6 +++ 9 files changed, 71 insertions(+), 40 deletions(-) create mode 100644 LongTests/Parallelism.cs diff --git a/DistTestCore/ByteSize.cs b/DistTestCore/ByteSize.cs index 4760c83..28ec49c 100644 --- a/DistTestCore/ByteSize.cs +++ b/DistTestCore/ByteSize.cs @@ -12,6 +12,11 @@ public long SizeInBytes { get; } + public long ToMB() + { + return SizeInBytes / (1024 * 1024); + } + public override bool Equals(object? obj) { return obj is ByteSize size && SizeInBytes == size.SizeInBytes; diff --git a/DistTestCore/Codex/CodexContainerRecipe.cs b/DistTestCore/Codex/CodexContainerRecipe.cs index 5b25a2f..f327927 100644 --- a/DistTestCore/Codex/CodexContainerRecipe.cs +++ b/DistTestCore/Codex/CodexContainerRecipe.cs @@ -14,6 +14,10 @@ namespace DistTestCore.Codex public const string MetricsPortTag = "metrics_port"; public const string DiscoveryPortTag = "discovery-port"; + // Used by tests for time-constraint assersions. + public static readonly TimeSpan MaxUploadTimePerMegabyte = TimeSpan.FromSeconds(2.0); + public static readonly TimeSpan MaxDownloadTimePerMegabyte = TimeSpan.FromSeconds(2.0); + protected override string Image => DockerImage; protected override void Initialize(StartupConfig startupConfig) diff --git a/DistTestCore/DistTest.cs b/DistTestCore/DistTest.cs index df345e8..a93c180 100644 --- a/DistTestCore/DistTest.cs +++ b/DistTestCore/DistTest.cs @@ -10,7 +10,6 @@ using System.Reflection; namespace DistTestCore { - [SetUpFixture] [Parallelizable(ParallelScope.All)] public abstract class DistTest { diff --git a/DistTestCore/Helpers/PeerDownloadTestHelpers.cs b/DistTestCore/Helpers/PeerDownloadTestHelpers.cs index 0ce642b..a39e945 100644 --- a/DistTestCore/Helpers/PeerDownloadTestHelpers.cs +++ b/DistTestCore/Helpers/PeerDownloadTestHelpers.cs @@ -1,4 +1,5 @@ -using NUnit.Framework; +using DistTestCore.Codex; +using NUnit.Framework; namespace DistTestCore.Helpers { @@ -30,21 +31,19 @@ namespace DistTestCore.Helpers test.Log($"Success! Full download interconnectivity for nodes: {string.Join(",", nodes.Select(n => n.GetName()))}"); var timeTaken = DateTime.UtcNow - start; - AssertTimePerDownload(timeTaken, nodes.Count(), testFileSize); + AssertTimePerMB(timeTaken, nodes.Count(), testFileSize); } - private void AssertTimePerDownload(TimeSpan timeTaken, int numberOfNodes, ByteSize size) + private void AssertTimePerMB(TimeSpan timeTaken, int numberOfNodes, ByteSize size) { var numberOfDownloads = numberOfNodes * (numberOfNodes - 1); var timePerDownload = timeTaken / numberOfDownloads; - float sizeInMB = size.SizeInBytes / (1024.0f * 1024.0f); - var timePerMB = timePerDownload.TotalSeconds / sizeInMB; + float sizeInMB = size.ToMB(); + var timePerMB = timePerDownload / sizeInMB; test.Log($"Performed {numberOfDownloads} downloads of {size} in {timeTaken.TotalSeconds} seconds, for an average of {timePerMB} seconds per MB."); - var maxTimePerMB = 2.0f; - - Assert.That(timePerMB, Is.LessThan(maxTimePerMB), "Seconds-per-MB performance threshold breached."); + Assert.That(timePerMB, Is.LessThan(CodexContainerRecipe.MaxDownloadTimePerMegabyte), "MaxDownloadTimePerMegabyte performance threshold breached."); } private void PerformTest(IOnlineCodexNode uploader, IOnlineCodexNode[] downloaders, ByteSize testFileSize) diff --git a/DistTestCore/OnlineCodexNode.cs b/DistTestCore/OnlineCodexNode.cs index 270ebc1..46ca044 100644 --- a/DistTestCore/OnlineCodexNode.cs +++ b/DistTestCore/OnlineCodexNode.cs @@ -2,6 +2,7 @@ using DistTestCore.Logs; using DistTestCore.Marketplace; using DistTestCore.Metrics; +using Logging; using NUnit.Framework; namespace DistTestCore @@ -66,9 +67,14 @@ namespace DistTestCore public ContentId UploadFile(TestFile file) { - Log($"Uploading file '{file.Describe()}' of size {file.GetFileSize()}..."); using var fileStream = File.OpenRead(file.Filename); - var response = CodexAccess.UploadFile(fileStream); + + var logMessage = $"Uploading file '{file.Describe()}' of size {file.GetFileSize()}..."; + var response = Stopwatch.Measure(lifecycle.Log, logMessage, () => + { + return CodexAccess.UploadFile(fileStream); + }); + if (response.StartsWith(UploadFailedMessage)) { Assert.Fail("Node failed to store block."); @@ -82,9 +88,9 @@ namespace DistTestCore public TestFile? DownloadContent(ContentId contentId, string fileLabel = "") { - Log($"Downloading for contentId: '{contentId.Id}'..."); + var logMessage = $"Downloading for contentId: '{contentId.Id}'..."; var file = lifecycle.FileManager.CreateEmptyTestFile(fileLabel); - DownloadToFile(contentId.Id, file); + Stopwatch.Measure(lifecycle.Log, logMessage, () => DownloadToFile(contentId.Id, file)); Log($"Downloaded file '{file.Describe()}' of size {file.GetFileSize()} to '{file.Filename}'."); return file; } diff --git a/Logging/Stopwatch.cs b/Logging/Stopwatch.cs index 9f8a346..f62f7f6 100644 --- a/Logging/Stopwatch.cs +++ b/Logging/Stopwatch.cs @@ -23,6 +23,14 @@ namespace Logging sw.End(); } + public static T Measure(BaseLog log, string name, Func action, bool debug = false) + { + var sw = Begin(log, name, debug); + var result = action(); + sw.End(); + return result; + } + public static Stopwatch Begin(BaseLog log) { return Begin(log, ""); diff --git a/LongTests/BasicTests/DownloadTests.cs b/LongTests/BasicTests/DownloadTests.cs index 828cdaa..5034462 100644 --- a/LongTests/BasicTests/DownloadTests.cs +++ b/LongTests/BasicTests/DownloadTests.cs @@ -6,25 +6,6 @@ namespace TestsLong.BasicTests [TestFixture] public class DownloadTests : DistTest { - [Test] - [Combinatorial] - [UseLongTimeouts] - public void DownloadCorrectnessTest( - [Values(1, 10, 100, 1024)] int sizeInMB, - [Values(1, 10, 100, 1024)] int multiplier) - { - var size = (sizeInMB * multiplier).MB(); - - var expectedFile = GenerateTestFile(size); - - var node = SetupCodexNode(); - var cid = node.UploadFile(expectedFile); - var actualFile = node.DownloadContent(cid); - - expectedFile.AssertIsEqual(actualFile); - } - - [TestCase(3, 500)] [TestCase(5, 100)] [TestCase(10, 256)] diff --git a/LongTests/BasicTests/LargeFileTests.cs b/LongTests/BasicTests/LargeFileTests.cs index 3149ee3..636ff79 100644 --- a/LongTests/BasicTests/LargeFileTests.cs +++ b/LongTests/BasicTests/LargeFileTests.cs @@ -1,4 +1,5 @@ using DistTestCore; +using DistTestCore.Codex; using NUnit.Framework; namespace TestsLong.BasicTests @@ -6,19 +7,41 @@ namespace TestsLong.BasicTests [TestFixture] public class LargeFileTests : DistTest { - [Test, UseLongTimeouts] - public void OneClientLargeFileTest() + [Test] + [Combinatorial] + [UseLongTimeouts] + public void DownloadCorrectnessTest( + [Values(1, 10, 100, 1024)] int sizeInMB, + [Values(1, 10, 100, 1024)] int multiplier) { - var primary = SetupCodexNode(s => s - .WithStorageQuota(20.GB())); + var size = (sizeInMB * multiplier).MB(); - var testFile = GenerateTestFile(10.GB()); + var expectedFile = GenerateTestFile(size); - var contentId = primary.UploadFile(testFile); + var node = SetupCodexNode(); - var downloadedFile = primary.DownloadContent(contentId); + var uploadStart = DateTime.UtcNow; + var cid = node.UploadFile(expectedFile); + var downloadStart = DateTime.UtcNow; + var actualFile = node.DownloadContent(cid); + var downloadFinished = DateTime.UtcNow; + + expectedFile.AssertIsEqual(actualFile); + AssertTimeConstraint(uploadStart, downloadStart, downloadFinished, size); + } + + private void AssertTimeConstraint(DateTime uploadStart, DateTime downloadStart, DateTime downloadFinished, ByteSize size) + { + float sizeInMB = size.ToMB(); + var uploadTimePerMB = (uploadStart - downloadStart) / sizeInMB; + var downloadTimePerMB = (downloadStart - downloadFinished) / sizeInMB; + + Assert.That(uploadTimePerMB, Is.LessThan(CodexContainerRecipe.MaxUploadTimePerMegabyte), + "MaxUploadTimePerMegabyte performance threshold breached."); + + Assert.That(downloadTimePerMB, Is.LessThan(CodexContainerRecipe.MaxDownloadTimePerMegabyte), + "MaxDownloadTimePerMegabyte performance threshold breached."); - testFile.AssertIsEqual(downloadedFile); } } } diff --git a/LongTests/Parallelism.cs b/LongTests/Parallelism.cs new file mode 100644 index 0000000..f45d8f2 --- /dev/null +++ b/LongTests/Parallelism.cs @@ -0,0 +1,6 @@ +using NUnit.Framework; + +[assembly: LevelOfParallelism(1)] +namespace Tests +{ +}