89 lines
3.1 KiB
C#
89 lines
3.1 KiB
C#
using Xunit;
|
|
using XWorld.Server.Gateway;
|
|
|
|
namespace XWorld.Server.Gateway.Tests
|
|
{
|
|
public class MatchmakerTests
|
|
{
|
|
[Fact]
|
|
public void TwoEnqueues_SameBucket_PlayerCount2_Poll_ReturnsTwoHumanMatch()
|
|
{
|
|
var mm = new Matchmaker(timeoutTicks: 100);
|
|
mm.Enqueue(pid: 1, gameId: "rps", version: 1, playerCount: 2, tick: 0);
|
|
mm.Enqueue(pid: 2, gameId: "rps", version: 1, playerCount: 2, tick: 0);
|
|
|
|
var matches = mm.Poll(currentTick: 0);
|
|
|
|
Assert.Single(matches);
|
|
var m = matches[0];
|
|
Assert.Equal("rps", m.GameId);
|
|
Assert.Equal(1, m.Version);
|
|
Assert.Equal(2, m.Seats.Count);
|
|
Assert.False(m.Seats[0].IsAi);
|
|
Assert.False(m.Seats[1].IsAi);
|
|
Assert.Equal(1, m.Seats[0].PlayerId);
|
|
Assert.Equal(2, m.Seats[1].PlayerId);
|
|
}
|
|
|
|
[Fact]
|
|
public void SingleEnqueue_PollAfterTimeout_Returns1Human1AiMatch()
|
|
{
|
|
var mm = new Matchmaker(timeoutTicks: 10);
|
|
mm.Enqueue(pid: 7, gameId: "rps", version: 1, playerCount: 2, tick: 0);
|
|
|
|
// Not timed out yet
|
|
var early = mm.Poll(currentTick: 9);
|
|
Assert.Empty(early);
|
|
|
|
// Now timed out (currentTick - enqueuedTick > timeoutTicks → 11 - 0 = 11 > 10)
|
|
var matches = mm.Poll(currentTick: 10);
|
|
|
|
Assert.Single(matches);
|
|
var m = matches[0];
|
|
Assert.Equal(2, m.Seats.Count);
|
|
// First seat is the real player
|
|
Assert.False(m.Seats[0].IsAi);
|
|
Assert.Equal(7, m.Seats[0].PlayerId);
|
|
// Second seat is AI with negative pid
|
|
Assert.True(m.Seats[1].IsAi);
|
|
Assert.True(m.Seats[1].PlayerId < 0);
|
|
}
|
|
|
|
[Fact]
|
|
public void NotFull_NotTimedOut_Poll_ReturnsEmpty()
|
|
{
|
|
var mm = new Matchmaker(timeoutTicks: 100);
|
|
mm.Enqueue(pid: 3, gameId: "rps", version: 1, playerCount: 2, tick: 5);
|
|
|
|
var matches = mm.Poll(currentTick: 50); // 50-5=45 <= 100, not timed out, not full
|
|
|
|
Assert.Empty(matches);
|
|
}
|
|
|
|
[Fact]
|
|
public void PlayerCount1_SingleEnqueue_PollImmediately_ReturnsMatch()
|
|
{
|
|
// playerCount=1 应立即成团(Matchmaker 仅按 playerCount 分桶,不加载具体游戏)
|
|
var mm = new Matchmaker(timeoutTicks: 100);
|
|
mm.Enqueue(pid: 5, gameId: "solo1p", version: 1, playerCount: 1, tick: 0);
|
|
|
|
var matches = mm.Poll(currentTick: 0);
|
|
|
|
Assert.Single(matches);
|
|
Assert.Single(matches[0].Seats);
|
|
Assert.False(matches[0].Seats[0].IsAi);
|
|
}
|
|
|
|
[Fact]
|
|
public void Remove_DequeuesWaiter_SoNoMatchForms()
|
|
{
|
|
var mm = new Matchmaker(timeoutTicks: 100);
|
|
mm.Enqueue(1, "rps", 1, 2, tick: 0);
|
|
Assert.True(mm.Remove(1));
|
|
mm.Enqueue(2, "rps", 1, 2, tick: 0); // 只剩玩家2,凑不齐2人
|
|
Assert.Empty(mm.Poll(1)); // 未满未超时 → 无对局
|
|
Assert.False(mm.Remove(999)); // 不存在的 pid
|
|
}
|
|
}
|
|
}
|