using System.Collections.Generic; using Xunit; using XWorld.Framework; using XWorld.Framework.Protocol; using XWorld.Server.Gateway; namespace XWorld.Server.Gateway.Tests { public class RoomOutputSinkTests { [Fact] public void Broadcast_WrapsInGameChannelFrame_ToConnectedPlayers() { var sm = new SessionManager(); var c1 = new FakeConnection(1); var c2 = new FakeConnection(2); sm.OnConnect(1, c1); sm.OnConnect(2, c2); var sink = new RoomOutputSink("r1", new List { 1, 2 }, sm); sink.Broadcast(new NetMessage(7, new byte[] { 9, 9 })); Assert.Single(c1.Sent); Assert.Single(c2.Sent); var f = FrameCodec.Decode(c1.Sent[0]); Assert.Equal(Channel.Game, f.Channel); Assert.Equal((ushort)7, f.Opcode); Assert.Equal(new byte[] { 9, 9 }, f.Payload); } [Fact] public void Broadcast_SkipsDisconnectedPlayer() { var sm = new SessionManager(); var c1 = new FakeConnection(1); sm.OnConnect(1, c1); sm.OnConnect(2, new FakeConnection(2)); sm.OnDisconnect(2, sm.GetConnection(2), 0); // 玩家2 离线 var sink = new RoomOutputSink("r1", new List { 1, 2 }, sm); sink.Broadcast(new NetMessage(1, new byte[0])); Assert.Single(c1.Sent); // 仅在线玩家收到,不抛异常 } [Fact] public void SendTo_OnlyTargetPlayer() { var sm = new SessionManager(); var c1 = new FakeConnection(1); var c2 = new FakeConnection(2); sm.OnConnect(1, c1); sm.OnConnect(2, c2); var sink = new RoomOutputSink("r1", new List { 1, 2 }, sm); sink.SendTo(2, new NetMessage(5, new byte[] { 1 })); Assert.Empty(c1.Sent); Assert.Single(c2.Sent); } [Fact] public void Broadcast_AfterReconnect_GoesToNewConnection() { var sm = new SessionManager(); var c1 = new FakeConnection(1); sm.OnConnect(1, c1); var sink = new RoomOutputSink("r1", new List { 1 }, sm); sink.Broadcast(new NetMessage(1, new byte[] { 1 })); Assert.Single(c1.Sent); // 断线后重连到新连接 sm.OnDisconnect(1, c1, 0); var c2 = new FakeConnection(1); sm.OnConnect(1, c2); sink.Broadcast(new NetMessage(1, new byte[] { 2 })); Assert.Single(c1.Sent); // 旧连接不再收到 Assert.Single(c2.Sent); // 新连接收到 } } }