71 lines
3.9 KiB
C#
71 lines
3.9 KiB
C#
using System.Net;
|
|
using System.Net.Sockets;
|
|
using Cysharp.Threading.Tasks;
|
|
using NUnit.Framework;
|
|
using ShrinkNetwork;
|
|
|
|
[NonParallelizable]
|
|
public class NetworkTransportTests
|
|
{
|
|
[Test]
|
|
public async Task TcpRpcRoundTripAndCanceledSendPreserveNextFrame()
|
|
{
|
|
var reservation = new TcpListener(IPAddress.Loopback, 0); reservation.Start();
|
|
var port = ((IPEndPoint)reservation.LocalEndpoint).Port; reservation.Stop();
|
|
var serverTransport = new ShrinkTcpServerTransport(IPAddress.Loopback, port);
|
|
var clientTransport = new ShrinkTcpClientTransport("127.0.0.1", port);
|
|
var server = Service(); var client = Service();
|
|
var connected = new TaskCompletionSource<ShrinkNetworkSession>(TaskCreationOptions.RunContinuationsAsynchronously);
|
|
client.OnSessionConnected += session => connected.TrySetResult(session);
|
|
server.RegisterRequestHandler<Request, Response>((_, request) => UniTask.FromResult(new Response { Text = request.Text }));
|
|
try
|
|
{
|
|
server.BindTransport(serverTransport); client.BindTransport(clientTransport);
|
|
var session = await connected.Task.WaitAsync(TimeSpan.FromSeconds(5));
|
|
using var cancellation = new CancellationTokenSource(); cancellation.Cancel();
|
|
Assert.CatchAsync<OperationCanceledException>(async () => await clientTransport.SendAsync(1, new ReadOnlyMemory<byte>(new byte[100]), cancellation.Token));
|
|
var reply = await client.CallAsync<Request, Response>(session, new Request { Text = new string('t', 32768) }).AsTask().WaitAsync(TimeSpan.FromSeconds(5));
|
|
Assert.That(reply.Text.Length, Is.EqualTo(32768));
|
|
Assert.That(client.GetDiagnosticsSnapshot().RpcCompleted, Is.EqualTo(1));
|
|
}
|
|
finally { clientTransport.Stop(); serverTransport.Stop(); }
|
|
}
|
|
|
|
[Test]
|
|
public async Task NestedRpcResponseBypassesSerialHandlerQueue()
|
|
{
|
|
var a = new ShrinkLoopbackTransport(); var b = new ShrinkLoopbackTransport(); a.LinkPeer(b);
|
|
var client = Service(); var server = Service();
|
|
client.RegisterRequestHandler<Request, Response>((_, req) => UniTask.FromResult(new Response { Text = "nested:" + req.Text }));
|
|
server.RegisterRequestHandler<Request, Response>(async (ctx, req) => await server.CallAsync<Request, Response>(ctx.Session, req));
|
|
client.BindTransport(a); server.BindTransport(b); a.OpenSession(1);
|
|
var response = await client.CallAsync<Request, Response>(client.Sessions[1], new Request { Text = "ok" }).AsTask().WaitAsync(TimeSpan.FromSeconds(3));
|
|
Assert.That(response.Text, Is.EqualTo("nested:ok"));
|
|
a.Stop(); b.Stop();
|
|
}
|
|
|
|
[Test]
|
|
public async Task CongestionDisconnectsReliablePeerAndDoesNotResurrectSession()
|
|
{
|
|
var a = new ShrinkLoopbackTransport(); var b = new ShrinkLoopbackTransport(); a.LinkPeer(b);
|
|
using var queue = new ShrinkNetworkDispatchQueue(1, byteCapacity: 1024);
|
|
var client = Service(); var server = Service(); server.DispatchScheduler = queue;
|
|
client.BindTransport(a); server.BindTransport(b); a.OpenSession(1);
|
|
var session = client.Sessions[1];
|
|
var rejected = 0; server.OnDispatchRejected += _ => rejected++;
|
|
await client.SendAsync(session, new Request());
|
|
await client.SendAsync(session, new Request());
|
|
Assert.That(rejected, Is.EqualTo(1));
|
|
Assert.That(server.Sessions, Is.Empty);
|
|
await queue.PumpAsync(1);
|
|
Assert.That(server.Sessions, Is.Empty);
|
|
a.Stop(); b.Stop();
|
|
}
|
|
private static ShrinkNetworkService Service()
|
|
{
|
|
var service = new ShrinkNetworkService(); service.RegisterMessage<Request>(1); service.RegisterMessage<Response>(2); return service;
|
|
}
|
|
public sealed class Request : IShrinkNetworkRequest { public string Text { get; set; } = ""; }
|
|
public sealed class Response : ShrinkRpcResponseBase { public string Text { get; set; } = ""; }
|
|
}
|