Cleanup of peer connection helpers. Adds peer download helpers.

This commit is contained in:
benbierens 2023-05-29 09:13:38 +02:00
parent ab7a334987
commit 1016f568b8
No known key found for this signature in database
GPG Key ID: FE44815D96D0A1AA
6 changed files with 131 additions and 28 deletions

View File

@ -1,4 +1,5 @@
using DistTestCore.Codex; using DistTestCore.Codex;
using DistTestCore.Helpers;
using DistTestCore.Logs; using DistTestCore.Logs;
using DistTestCore.Marketplace; using DistTestCore.Marketplace;
using DistTestCore.Metrics; using DistTestCore.Metrics;
@ -25,8 +26,14 @@ namespace DistTestCore
testAssemblies = assemblies.Where(a => a.FullName!.ToLowerInvariant().Contains("test")).ToArray(); testAssemblies = assemblies.Where(a => a.FullName!.ToLowerInvariant().Contains("test")).ToArray();
fixtureLog = new FixtureLog(configuration.GetLogConfig()); fixtureLog = new FixtureLog(configuration.GetLogConfig());
PeerConnectionTestHelpers = new PeerConnectionTestHelpers(this);
PeerDownloadTestHelpers = new PeerDownloadTestHelpers(this);
} }
public PeerConnectionTestHelpers PeerConnectionTestHelpers { get; }
public PeerDownloadTestHelpers PeerDownloadTestHelpers { get; }
[OneTimeSetUp] [OneTimeSetUp]
public void GlobalSetup() public void GlobalSetup()
{ {
@ -85,6 +92,17 @@ namespace DistTestCore
return Get().FileManager.GenerateTestFile(size); return Get().FileManager.GenerateTestFile(size);
} }
/// <summary>
/// Any test files generated in 'action' will be deleted after it returns.
/// This helps prevent large tests from filling up discs.
/// </summary>
public void ScopedTestFiles(Action action)
{
Get().FileManager.PushFileSet();
action();
Get().FileManager.PopFileSet();
}
public IOnlineCodexNode SetupCodexBootstrapNode() public IOnlineCodexNode SetupCodexBootstrapNode()
{ {
return SetupCodexBootstrapNode(s => { }); return SetupCodexBootstrapNode(s => { });
@ -133,18 +151,18 @@ namespace DistTestCore
return Get().CodexStarter.RunningGroups.SelectMany(g => g.Nodes); return Get().CodexStarter.RunningGroups.SelectMany(g => g.Nodes);
} }
protected BaseLog GetTestLog() public BaseLog GetTestLog()
{ {
return Get().Log; return Get().Log;
} }
protected void Log(string msg) public void Log(string msg)
{ {
TestContext.Progress.WriteLine(msg); TestContext.Progress.WriteLine(msg);
GetTestLog().Log(msg); GetTestLog().Log(msg);
} }
protected void Debug(string msg) public void Debug(string msg)
{ {
TestContext.Progress.WriteLine(msg); TestContext.Progress.WriteLine(msg);
GetTestLog().Debug(msg); GetTestLog().Debug(msg);

View File

@ -9,6 +9,8 @@ namespace DistTestCore
TestFile CreateEmptyTestFile(); TestFile CreateEmptyTestFile();
TestFile GenerateTestFile(ByteSize size); TestFile GenerateTestFile(ByteSize size);
void DeleteAllTestFiles(); void DeleteAllTestFiles();
void PushFileSet();
void PopFileSet();
} }
public class FileManager : IFileManager public class FileManager : IFileManager
@ -18,6 +20,7 @@ namespace DistTestCore
private readonly Random random = new Random(); private readonly Random random = new Random();
private readonly TestLog log; private readonly TestLog log;
private readonly string folder; private readonly string folder;
private readonly List<List<TestFile>> fileSetStack = new List<List<TestFile>>();
public FileManager(TestLog log, Configuration configuration) public FileManager(TestLog log, Configuration configuration)
{ {
@ -31,6 +34,7 @@ namespace DistTestCore
{ {
var result = new TestFile(Path.Combine(folder, Guid.NewGuid().ToString() + "_test.bin")); var result = new TestFile(Path.Combine(folder, Guid.NewGuid().ToString() + "_test.bin"));
File.Create(result.Filename).Close(); File.Create(result.Filename).Close();
if (fileSetStack.Any()) fileSetStack.Last().Add(result);
return result; return result;
} }
@ -47,6 +51,27 @@ namespace DistTestCore
DeleteDirectory(); DeleteDirectory();
} }
public void PushFileSet()
{
fileSetStack.Add(new List<TestFile>());
}
public void PopFileSet()
{
if (!fileSetStack.Any()) return;
var pop = fileSetStack.Last();
fileSetStack.Remove(pop);
foreach (var file in pop)
{
try
{
File.Delete(file.Filename);
}
catch { }
}
}
private void GenerateFileBytes(TestFile result, ByteSize size) private void GenerateFileBytes(TestFile result, ByteSize size)
{ {
long bytesLeft = size.SizeInBytes; long bytesLeft = size.SizeInBytes;

View File

@ -1,28 +1,32 @@
using DistTestCore.Codex; using DistTestCore.Codex;
using DistTestCore;
using NUnit.Framework; using NUnit.Framework;
using Logging;
using Utils; using Utils;
namespace Tests.PeerDiscoveryTests namespace DistTestCore.Helpers
{ {
public static class PeerTestHelpers public class PeerConnectionTestHelpers
{ {
private static readonly Random random = new Random(); private readonly Random random = new Random();
private readonly DistTest test;
public static void AssertFullyConnected(IEnumerable<IOnlineCodexNode> nodes, BaseLog? log = null) public PeerConnectionTestHelpers(DistTest test)
{ {
AssertFullyConnected(log, nodes.ToArray()); this.test = test;
} }
public static void AssertFullyConnected(BaseLog? log = null, params IOnlineCodexNode[] nodes) public void AssertFullyConnected(IEnumerable<IOnlineCodexNode> nodes)
{
AssertFullyConnected(nodes.ToArray());
}
public void AssertFullyConnected(params IOnlineCodexNode[] nodes)
{ {
var entries = CreateEntries(nodes); var entries = CreateEntries(nodes);
var pairs = CreatePairs(entries); var pairs = CreatePairs(entries);
RetryWhilePairs(pairs, () => RetryWhilePairs(pairs, () =>
{ {
CheckAndRemoveSuccessful(pairs, log); CheckAndRemoveSuccessful(pairs);
}); });
if (pairs.Any()) if (pairs.Any())
@ -34,7 +38,7 @@ namespace Tests.PeerDiscoveryTests
private static void RetryWhilePairs(List<Pair> pairs, Action action) private static void RetryWhilePairs(List<Pair> pairs, Action action)
{ {
var timeout = DateTime.UtcNow + TimeSpan.FromMinutes(5); var timeout = DateTime.UtcNow + TimeSpan.FromMinutes(5);
while (pairs.Any() && (timeout > DateTime.UtcNow)) while (pairs.Any() && timeout > DateTime.UtcNow)
{ {
action(); action();
@ -42,15 +46,21 @@ namespace Tests.PeerDiscoveryTests
} }
} }
private static void CheckAndRemoveSuccessful(List<Pair> pairs, BaseLog? log) private void CheckAndRemoveSuccessful(List<Pair> pairs)
{ {
var checkTasks = pairs.Select(p => Task.Run(p.Check)).ToArray(); var checkTasks = pairs.Select(p => Task.Run(() =>
{
ApplyRandomDelay();
p.Check();
})).ToArray();
Task.WaitAll(checkTasks); Task.WaitAll(checkTasks);
foreach (var pair in pairs.ToArray()) foreach (var pair in pairs.ToArray())
{ {
if (pair.Success) if (pair.Success)
{ {
test.Debug(pair.GetMessage());
pairs.Remove(pair); pairs.Remove(pair);
} }
} }
@ -86,6 +96,12 @@ namespace Tests.PeerDiscoveryTests
} }
} }
private void ApplyRandomDelay()
{
// Calling all the nodes all at the same time is not exactly nice.
Time.Sleep(TimeSpan.FromMicroseconds(random.Next(10, 100)));
}
public class Entry public class Entry
{ {
public Entry(IOnlineCodexNode node) public Entry(IOnlineCodexNode node)
@ -141,7 +157,6 @@ namespace Tests.PeerDiscoveryTests
public void Check() public void Check()
{ {
ApplyRandomDelay();
aToBTime = Measure(() => AKnowsB = Knows(A, B)); aToBTime = Measure(() => AKnowsB = Knows(A, B));
bToATime = Measure(() => BKnowsA = Knows(B, A)); bToATime = Measure(() => BKnowsA = Knows(B, A));
} }
@ -179,12 +194,6 @@ namespace Tests.PeerDiscoveryTests
return $" ({aName}->{bName}: {aToBTime.TotalMinutes} seconds, {bName}->{aName}: {bToATime.TotalSeconds} seconds)"; return $" ({aName}->{bName}: {aToBTime.TotalMinutes} seconds, {bName}->{aName}: {bToATime.TotalSeconds} seconds)";
} }
private static void ApplyRandomDelay()
{
// Calling all the nodes all at the same time is not exactly nice.
Time.Sleep(TimeSpan.FromMicroseconds(random.Next(10, 100)));
}
private static TimeSpan Measure(Action action) private static TimeSpan Measure(Action action)
{ {
var start = DateTime.UtcNow; var start = DateTime.UtcNow;

View File

@ -0,0 +1,49 @@
namespace DistTestCore.Helpers
{
public class PeerDownloadTestHelpers
{
private readonly DistTest test;
public PeerDownloadTestHelpers(DistTest test)
{
this.test = test;
}
public void AssertFullDownloadInterconnectivity(IEnumerable<IOnlineCodexNode> nodes)
{
AssertFullDownloadInterconnectivity(nodes, 1.MB());
}
public void AssertFullDownloadInterconnectivity(IEnumerable<IOnlineCodexNode> nodes, ByteSize testFileSize)
{
foreach (var node in nodes)
{
var uploader = node;
var downloaders = nodes.Where(n => n != uploader).ToArray();
test.ScopedTestFiles(() =>
{
PerformTest(uploader, downloaders);
});
}
}
private void PerformTest(IOnlineCodexNode uploader, IOnlineCodexNode[] downloaders)
{
// 1 test file per downloader.
var files = downloaders.Select(d => test.GenerateTestFile(1.MB())).ToArray();
// Upload all the test files to the uploader.
var contentIds = files.Select(uploader.UploadFile).ToArray();
// Each downloader should retrieve its own test file.
for (var i = 0; i < downloaders.Length; i++)
{
var expectedFile = files[i];
var downloadedFile = downloaders[i].DownloadContent(contentIds[i]);
expectedFile.AssertIsEqual(downloadedFile);
}
}
}
}

View File

@ -1,4 +1,5 @@
using DistTestCore; using DistTestCore;
using DistTestCore.Helpers;
using NUnit.Framework; using NUnit.Framework;
using Utils; using Utils;
@ -54,7 +55,7 @@ namespace Tests.PeerDiscoveryTests
private void AssertAllNodesConnected() private void AssertAllNodesConnected()
{ {
PeerTestHelpers.AssertFullyConnected(GetAllOnlineCodexNodes(), GetTestLog()); PeerConnectionTestHelpers.AssertFullyConnected(GetAllOnlineCodexNodes());
} }
} }
} }

View File

@ -1,5 +1,6 @@
using DistTestCore; using DistTestCore;
using DistTestCore.Codex; using DistTestCore.Codex;
using DistTestCore.Helpers;
using NUnit.Framework; using NUnit.Framework;
using Utils; using Utils;
@ -55,7 +56,7 @@ namespace Tests.PeerDiscoveryTests
private void AssertAllNodesConnected() private void AssertAllNodesConnected()
{ {
PeerTestHelpers.AssertFullyConnected(GetAllOnlineCodexNodes(), GetTestLog()); PeerConnectionTestHelpers.AssertFullyConnected(GetAllOnlineCodexNodes());
} }
} }
} }