using Xunit; using XWorld.Server.Gateway; namespace XWorld.Server.Gateway.Tests { public class SessionManagerTests { [Fact] public void Connect_NewPid_CreatesConnectedSession() { var sm = new SessionManager(); var c = new FakeConnection(1); sm.OnConnect(1, c); Assert.True(sm.IsConnected(1)); Assert.Same(c, sm.GetConnection(1)); } [Fact] public void Reconnect_SamePid_RebindsToNewConnection() { var sm = new SessionManager(); var c1 = new FakeConnection(1); var c2 = new FakeConnection(1); sm.OnConnect(1, c1); sm.OnDisconnect(1, c1, currentTick: 5); Assert.False(sm.IsConnected(1)); Assert.Null(sm.GetConnection(1)); sm.OnConnect(1, c2); // 重连 Assert.True(sm.IsConnected(1)); Assert.Same(c2, sm.GetConnection(1)); // 路由到新连接 } [Fact] public void StaleDisconnect_AfterReconnect_DoesNotClobber() { var sm = new SessionManager(); var c1 = new FakeConnection(1); var c2 = new FakeConnection(1); sm.OnConnect(1, c1); sm.OnConnect(1, c2); // 已重连到 c2 sm.OnDisconnect(1, c1, currentTick: 9); // 旧连接 c1 的迟到断线不应清掉 c2 Assert.True(sm.IsConnected(1)); Assert.Same(c2, sm.GetConnection(1)); } [Fact] public void RoomBinding_RoundTrips() { var sm = new SessionManager(); sm.OnConnect(1, new FakeConnection(1)); sm.Get(1).RoomId = "r1"; Assert.Equal("r1", sm.Get(1).RoomId); } [Fact] public void SweepExpired_RemovesSessionsPastWindow() { var sm = new SessionManager(); var conn = new FakeConnection(1); sm.OnConnect(1, conn); sm.OnDisconnect(1, conn, currentTick: 0); var none = sm.SweepExpired(currentTick: 3, windowTicks: 5); Assert.Empty(none); Assert.NotNull(sm.Get(1)); var removed = sm.SweepExpired(currentTick: 6, windowTicks: 5); // 6-0 > 5 Assert.Single(removed); Assert.Null(sm.Get(1)); } } }