84 lines
3.5 KiB
C#
84 lines
3.5 KiB
C#
using System.Threading.Tasks;
|
|
using Xunit;
|
|
using XWorld.Framework.Protocol;
|
|
using XWorld.Server.Gateway;
|
|
|
|
namespace XWorld.Server.Gateway.Tests
|
|
{
|
|
public class GatewayEndToEndTests
|
|
{
|
|
private static Frame JoinRps()
|
|
=> new Frame(Channel.Framework, (ushort)FrameworkOpcode.MatchRequest,
|
|
new MatchRequestMsg { GameId = "rps", Version = 1 }.Encode());
|
|
|
|
[Fact]
|
|
public async Task Heartbeat_IsEchoedBack()
|
|
{
|
|
var host = new GameServerHost();
|
|
await host.StartAsync(TestGames.Root, tickIntervalMs: 20);
|
|
try
|
|
{
|
|
using var client = new WsTestClient();
|
|
await client.ConnectAsync(host.WsBaseUrl, pid: 7);
|
|
await client.SendFrameAsync(new Frame(Channel.Framework, (ushort)FrameworkOpcode.Heartbeat,
|
|
new HeartbeatMsg { ClientTimeMs = 999L }.Encode()));
|
|
|
|
Frame? echo = null;
|
|
for (int i = 0; i < 10; i++)
|
|
{
|
|
var f = await client.ReceiveFrameAsync(5000);
|
|
if (f.Channel == Channel.Framework && f.Opcode == (ushort)FrameworkOpcode.Heartbeat) { echo = f; break; }
|
|
}
|
|
Assert.True(echo.HasValue, "未收到心跳回显");
|
|
Assert.Equal(999L, HeartbeatMsg.Decode(echo.Value.Payload).ClientTimeMs);
|
|
await client.CloseAsync();
|
|
}
|
|
finally { await host.StopAsync(); }
|
|
}
|
|
|
|
[Fact]
|
|
public async Task Reconnect_ContinuesReceivingFromSameRoom()
|
|
{
|
|
var host = new GameServerHost();
|
|
// matchTimeoutTicks=3 → 单人后 AI 兜底成团;logicalDt=0.2 让 60s 对局慢跑;大重连窗口
|
|
await host.StartAsync(TestGames.Root, tickIntervalMs: 200,
|
|
reconnectWindowTicks: 100, matchTimeoutTicks: 3, logicalDt: 0.2f);
|
|
try
|
|
{
|
|
var client1 = new WsTestClient();
|
|
await client1.ConnectAsync(host.WsBaseUrl, pid: 42);
|
|
await client1.SendFrameAsync(JoinRps());
|
|
|
|
// 收到 MatchFound 后的第一个游戏快照
|
|
bool gotSnapshot = false;
|
|
for (int i = 0; i < 15 && !gotSnapshot; i++)
|
|
{
|
|
var f = await client1.ReceiveFrameAsync(5000);
|
|
if (f.Channel == Channel.Game) gotSnapshot = true;
|
|
}
|
|
Assert.True(gotSnapshot, "重连前应先收到一个快照");
|
|
|
|
// 断开
|
|
await client1.CloseAsync();
|
|
client1.Dispose();
|
|
|
|
// 用同 pid 重连
|
|
using var client2 = new WsTestClient();
|
|
await client2.ConnectAsync(host.WsBaseUrl, pid: 42);
|
|
|
|
// 房间仍在跑,下一个房间输出应发到 client2
|
|
bool gotAfterReconnect = false;
|
|
for (int i = 0; i < 15 && !gotAfterReconnect; i++)
|
|
{
|
|
var f = await client2.ReceiveFrameAsync(5000);
|
|
if (f.Channel == Channel.Game) gotAfterReconnect = true;
|
|
else if (f.Channel == Channel.Framework && f.Opcode == (ushort)FrameworkOpcode.RoomEnd) gotAfterReconnect = true;
|
|
}
|
|
Assert.True(gotAfterReconnect, "重连后应继续收到房间输出(快照或 RoomEnd)");
|
|
await client2.CloseAsync();
|
|
}
|
|
finally { await host.StopAsync(); }
|
|
}
|
|
}
|
|
}
|