perf(tests): isolate network E2E and await QUIC cleanup
This commit is contained in:
1 parent
047df83a84
commit
0d08e90dab
20 files changed
+231
-181
No files matched your search
@@ -70,8 +70,10 @@ public sealed class ProbeSimulator : IAsyncDisposable
|
||||
|
||||
public async Task ConnectAsync(string host, int controlPort, byte[] agentPublicKey, int udpPort, NodeId agentId, TimeProvider? time = null, CancellationToken ct = default)
|
||||
{
|
||||
using var timeout = CancellationTokenSource.CreateLinkedTokenSource(ct);
|
||||
timeout.CancelAfter(TimeSpan.FromSeconds(10));
|
||||
_agentId = agentId;
|
||||
(PeerSessionInfo info, TlsFrameTransport transport) = await PeerConnector.ConnectAsync(host, controlPort, agentPublicKey, _identity, ProbeId, "0.0.0-sim", 8 << 20, time ?? TimeProvider.System, ct);
|
||||
(PeerSessionInfo info, TlsFrameTransport transport) = await PeerConnector.ConnectAsync(host, controlPort, agentPublicKey, _identity, ProbeId, "0.0.0-sim", 8 << 20, time ?? TimeProvider.System, timeout.Token);
|
||||
_info = info;
|
||||
_agentKey = agentPublicKey;
|
||||
_dataSession = new DataSession(info.Credentials.SessionIdValue, info.Credentials.Key);
|
||||
@@ -88,8 +90,8 @@ public sealed class ProbeSimulator : IAsyncDisposable
|
||||
_rpc.OnBinary = (_, _) => ValueTask.CompletedTask;
|
||||
_run = _rpc.RunAsync(_stop.Token);
|
||||
_receiver = _quic.RunAsync(_stop.Token);
|
||||
await SyncClockAsync();
|
||||
await _quic.ConnectAsync(ct);
|
||||
await SyncClockAsync(ct: timeout.Token);
|
||||
await _quic.ConnectAsync(timeout.Token);
|
||||
}
|
||||
|
||||
public async Task<LineTaskSet> WaitForTasksAsync(Func<LineTaskSet, bool> predicate, TimeSpan? timeout = null)
|
||||
@@ -111,16 +113,27 @@ public sealed class ProbeSimulator : IAsyncDisposable
|
||||
}
|
||||
|
||||
/// <summary>NTP 式的时钟同步:偏移 = Agent 时钟 − (往返中点的) Probe 时钟。取最小往返的一次。</summary>
|
||||
public async Task SyncClockAsync(int rounds = 5)
|
||||
public async Task SyncClockAsync(int rounds = 3, CancellationToken ct = default)
|
||||
{
|
||||
long bestRoundTrip = long.MaxValue;
|
||||
for (int i = 0; i < rounds; i++)
|
||||
{
|
||||
long t0 = NowUs();
|
||||
Result<ClockResult> reply = await _rpc!.RequestAsync(MoShiroMethods.Clock, new ClockParams { ProbeMonoUs = t0 }, MoShiroJsonContext.Default.ClockParams, MoShiroJsonContext.Default.ClockResult, CancellationToken.None);
|
||||
Result<ClockResult> reply = await _rpc!.RequestAsync(
|
||||
MoShiroMethods.Clock,
|
||||
new ClockParams { ProbeMonoUs = t0 },
|
||||
MoShiroJsonContext.Default.ClockParams,
|
||||
MoShiroJsonContext.Default.ClockResult,
|
||||
ct,
|
||||
TimeSpan.FromSeconds(2));
|
||||
long t1 = NowUs();
|
||||
if (!reply.IsSuccess)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
long roundTrip = t1 - t0;
|
||||
if (reply.IsSuccess && roundTrip < bestRoundTrip)
|
||||
if (roundTrip < bestRoundTrip)
|
||||
{
|
||||
bestRoundTrip = roundTrip;
|
||||
ClockOffsetUs = reply.Value.AgentMonoUs - ((t0 + t1) / 2);
|
||||
@@ -164,6 +177,9 @@ public sealed class ProbeSimulator : IAsyncDisposable
|
||||
/// <summary>对一个 tcp_echo 线路任务建立一条 TCP(可选 TLS)连接,发 <paramref name="count"/> 条回显消息,然后交出一个列块。</summary>
|
||||
public async Task<(int Sent, int Received)> RunTcpEchoAsync(LineTask task, int tcpPort, int count, TimeSpan interval, bool tls, CancellationToken ct = default)
|
||||
{
|
||||
using var timeout = CancellationTokenSource.CreateLinkedTokenSource(ct);
|
||||
timeout.CancelAfter(TimeSpan.FromSeconds(15));
|
||||
ct = timeout.Token;
|
||||
using var client = new System.Net.Sockets.TcpClient();
|
||||
await client.ConnectAsync(IPAddress.Loopback, tcpPort, ct);
|
||||
Stream stream = client.GetStream();
|
||||
@@ -246,10 +262,20 @@ public sealed class ProbeSimulator : IAsyncDisposable
|
||||
public async ValueTask DisposeAsync()
|
||||
{
|
||||
await _stop.CancelAsync();
|
||||
_quic?.Dispose();
|
||||
if (_quic is not null)
|
||||
{
|
||||
await _quic.DisposeAsync();
|
||||
}
|
||||
if (_rpc is not null)
|
||||
{
|
||||
await _rpc.DisposeAsync();
|
||||
try
|
||||
{
|
||||
await _rpc.DisposeAsync().AsTask().WaitAsync(TimeSpan.FromSeconds(2));
|
||||
}
|
||||
catch (Exception ex) when (ex is TimeoutException or OperationCanceledException or IOException or ObjectDisposedException)
|
||||
{
|
||||
// 测试连接关闭属于尽力清理,不能让一条卡住的流拖住整个测试程序集。
|
||||
}
|
||||
}
|
||||
|
||||
foreach (Task? task in new[] { _run, _receiver })
|
||||
|
||||
Reference in new issue
Block a user