Files
Rendezvous/tests/FinalFactory.Rendezvous.Tests/TestClient/DirectEchoProtocolTests.cs
T
KyuubiYoru 7e3be2cad1
quality-gate / quality (push) Failing after 1m3s
feat(tooling): add standalone rendezvous test client (#25)
2026-07-16 11:05:56 +02:00

136 lines
4.8 KiB
C#

using System.Net;
using System.Text;
using FinalFactory.Rendezvous.TestClient;
using LiteNetLib;
namespace FinalFactory.Rendezvous.Tests.TestClient;
public sealed class DirectEchoProtocolTests
{
[Fact]
public async Task HostReleasesPendingNonceWhenPeerDisconnectsBeforeAcknowledgement()
{
using CancellationTokenSource timeout = new(TimeSpan.FromSeconds(3));
EventBasedNetListener hostEvents = new();
EventBasedNetListener clientEvents = new();
hostEvents.ConnectionRequestEvent += request => request.Accept();
NetPeer? clientPeer = null;
clientEvents.PeerConnectedEvent += peer => clientPeer = peer;
NetManager hostManager = new(hostEvents);
NetManager clientManager = new(clientEvents);
try
{
Assert.True(hostManager.Start(0));
Assert.True(clientManager.Start(0));
clientManager.Connect(
new IPEndPoint(IPAddress.Loopback, hostManager.LocalPort),
"echo-test");
await PumpUntilAsync(
() => clientPeer is not null,
hostManager,
clientManager,
clientManager,
timeout.Token);
using DirectEchoProtocol host = new(hostEvents, host: true);
clientPeer!.Send(
Encoding.ASCII.GetBytes("rv1-ping:00112233445566778899aabbccddeeff"),
DeliveryMethod.ReliableOrdered);
await PumpUntilAsync(
() => host.PendingHostExchangeCount == 1,
hostManager,
clientManager,
clientManager,
timeout.Token);
clientPeer.Disconnect();
await PumpUntilAsync(
() => host.PendingHostExchangeCount == 0,
hostManager,
clientManager,
clientManager,
timeout.Token);
Assert.Equal(0, host.PendingHostExchangeCount);
}
finally
{
clientManager.Stop();
hostManager.Stop();
}
}
[Fact]
public async Task HostVerifiesOverlappingPeersAgainstTheirOwnNonces()
{
using CancellationTokenSource timeout = new(TimeSpan.FromSeconds(3));
EventBasedNetListener hostEvents = new();
EventBasedNetListener firstEvents = new();
EventBasedNetListener secondEvents = new();
hostEvents.ConnectionRequestEvent += request => request.Accept();
NetPeer? firstPeer = null;
NetPeer? secondPeer = null;
firstEvents.PeerConnectedEvent += peer => firstPeer = peer;
secondEvents.PeerConnectedEvent += peer => secondPeer = peer;
NetManager hostManager = new(hostEvents);
NetManager firstManager = new(firstEvents);
NetManager secondManager = new(secondEvents);
try
{
Assert.True(hostManager.Start(0));
Assert.True(firstManager.Start(0));
Assert.True(secondManager.Start(0));
IPEndPoint hostEndpoint = new(IPAddress.Loopback, hostManager.LocalPort);
firstManager.Connect(hostEndpoint, "echo-test");
secondManager.Connect(hostEndpoint, "echo-test");
await PumpUntilAsync(
() => firstPeer is not null && secondPeer is not null,
hostManager,
firstManager,
secondManager,
timeout.Token);
using DirectEchoProtocol host = new(hostEvents, host: true);
using DirectEchoProtocol first = new(firstEvents, host: false);
using DirectEchoProtocol second = new(secondEvents, host: false);
int hostCompletions = 0;
host.ExchangeCompleted += _ => hostCompletions++;
first.BeginJoin(firstPeer!);
second.BeginJoin(secondPeer!);
await PumpUntilAsync(
() => first.Completion.IsCompleted
&& second.Completion.IsCompleted
&& hostCompletions == 2,
hostManager,
firstManager,
secondManager,
timeout.Token);
Assert.Equal(2, hostCompletions);
}
finally
{
firstManager.Stop();
secondManager.Stop();
hostManager.Stop();
}
}
private static async Task PumpUntilAsync(
Func<bool> predicate,
NetManager host,
NetManager first,
NetManager second,
CancellationToken cancellationToken)
{
while (!predicate())
{
cancellationToken.ThrowIfCancellationRequested();
host.PollEvents();
first.PollEvents();
second.PollEvents();
await Task.Delay(2, cancellationToken);
}
}
}