151 lines
5.5 KiB
C#
151 lines
5.5 KiB
C#
using System.Collections.Generic;
|
|
using Xunit;
|
|
using XWorld.Framework;
|
|
using XWorld.Framework.Protocol;
|
|
|
|
namespace XWorld.Framework.Tests
|
|
{
|
|
public class FrameworkMessagesTests
|
|
{
|
|
[Fact]
|
|
public void Heartbeat_RoundTrips()
|
|
{
|
|
var m = new HeartbeatMsg { ClientTimeMs = 1_725_000_000_123L };
|
|
var d = HeartbeatMsg.Decode(m.Encode());
|
|
Assert.Equal(m.ClientTimeMs, d.ClientTimeMs);
|
|
}
|
|
|
|
[Fact]
|
|
public void MatchRequest_RoundTrips()
|
|
{
|
|
var m = new MatchRequestMsg { GameId = "rock_paper_scissors", Version = 3 };
|
|
var d = MatchRequestMsg.Decode(m.Encode());
|
|
Assert.Equal(m.GameId, d.GameId);
|
|
Assert.Equal(m.Version, d.Version);
|
|
}
|
|
|
|
[Fact]
|
|
public void MatchFound_RoundTrips_WithPlayers()
|
|
{
|
|
var m = new MatchFoundMsg
|
|
{
|
|
RoomId = "room-42",
|
|
Version = 3,
|
|
SelfPlayerId = 1001,
|
|
Players =
|
|
{
|
|
new PlayerInfo { PlayerId = 1001, Name = "Alice", IsAI = false },
|
|
new PlayerInfo { PlayerId = -1, Name = "AI", IsAI = true },
|
|
},
|
|
};
|
|
var d = MatchFoundMsg.Decode(m.Encode());
|
|
Assert.Equal("room-42", d.RoomId);
|
|
Assert.Equal(3, d.Version);
|
|
Assert.Equal(1001, d.SelfPlayerId);
|
|
Assert.Equal(2, d.Players.Count);
|
|
Assert.Equal(1001, d.Players[0].PlayerId);
|
|
Assert.Equal("Alice", d.Players[0].Name);
|
|
Assert.False(d.Players[0].IsAI);
|
|
Assert.Equal(-1, d.Players[1].PlayerId);
|
|
Assert.True(d.Players[1].IsAI);
|
|
}
|
|
|
|
[Fact]
|
|
public void GameInput_RoundTrips()
|
|
{
|
|
var m = new GameInputMsg { GameOpcode = 12, Payload = new byte[] { 9, 8, 7 } };
|
|
var d = GameInputMsg.Decode(m.Encode());
|
|
Assert.Equal((ushort)12, d.GameOpcode);
|
|
Assert.Equal(new byte[] { 9, 8, 7 }, d.Payload);
|
|
}
|
|
|
|
[Fact]
|
|
public void Snapshot_RoundTrips()
|
|
{
|
|
var m = new SnapshotMsg { Tick = 250, StateBlob = new byte[] { 0xDE, 0xAD } };
|
|
var d = SnapshotMsg.Decode(m.Encode());
|
|
Assert.Equal(250, d.Tick);
|
|
Assert.Equal(new byte[] { 0xDE, 0xAD }, d.StateBlob);
|
|
}
|
|
|
|
[Fact]
|
|
public void RoomEnd_RoundTrips()
|
|
{
|
|
var m = new RoomEndMsg { WinnerPlayerId = 1001, ResultBlob = new byte[] { 1 } };
|
|
var d = RoomEndMsg.Decode(m.Encode());
|
|
Assert.Equal(1001, d.WinnerPlayerId);
|
|
Assert.Equal(new byte[] { 1 }, d.ResultBlob);
|
|
}
|
|
|
|
[Fact]
|
|
public void Error_RoundTrips()
|
|
{
|
|
var m = new ErrorMsg { Code = 404, Message = "version mismatch" };
|
|
var d = ErrorMsg.Decode(m.Encode());
|
|
Assert.Equal(404, d.Code);
|
|
Assert.Equal("version mismatch", d.Message);
|
|
}
|
|
|
|
[Fact]
|
|
public void Opcodes_AreStableValues()
|
|
{
|
|
// 线网兼容性:opcode 数值固定,改动等于破坏协议
|
|
Assert.Equal((ushort)1, (ushort)FrameworkOpcode.Heartbeat);
|
|
Assert.Equal((ushort)2, (ushort)FrameworkOpcode.MatchRequest);
|
|
Assert.Equal((ushort)3, (ushort)FrameworkOpcode.MatchFound);
|
|
Assert.Equal((ushort)4, (ushort)FrameworkOpcode.GameInput);
|
|
Assert.Equal((ushort)5, (ushort)FrameworkOpcode.Snapshot);
|
|
Assert.Equal((ushort)6, (ushort)FrameworkOpcode.RoomEnd);
|
|
Assert.Equal((ushort)7, (ushort)FrameworkOpcode.Error);
|
|
}
|
|
|
|
[Fact]
|
|
public void Message_TravelsInsideFrame()
|
|
{
|
|
// 端到端:DTO -> payload -> Frame -> wire -> Frame -> DTO
|
|
var req = new MatchRequestMsg { GameId = "rps", Version = 1 };
|
|
var frame = new Frame(Channel.Framework, (ushort)FrameworkOpcode.MatchRequest, req.Encode());
|
|
byte[] wire = FrameCodec.Encode(frame);
|
|
|
|
Frame back = FrameCodec.Decode(wire);
|
|
Assert.Equal(Channel.Framework, back.Channel);
|
|
Assert.Equal((ushort)FrameworkOpcode.MatchRequest, back.Opcode);
|
|
var d = MatchRequestMsg.Decode(back.Payload);
|
|
Assert.Equal("rps", d.GameId);
|
|
Assert.Equal(1, d.Version);
|
|
}
|
|
|
|
[Fact]
|
|
public void GameInput_NullPayload_RoundTrips_AsEmpty()
|
|
{
|
|
var m = new GameInputMsg { GameOpcode = 5, Payload = null };
|
|
var d = GameInputMsg.Decode(m.Encode());
|
|
Assert.Equal((ushort)5, d.GameOpcode);
|
|
Assert.NotNull(d.Payload);
|
|
Assert.Empty(d.Payload);
|
|
}
|
|
|
|
[Fact]
|
|
public void Error_NullMessage_RoundTrips_AsEmpty()
|
|
{
|
|
var m = new ErrorMsg { Code = 7, Message = null };
|
|
var d = ErrorMsg.Decode(m.Encode());
|
|
Assert.Equal(7, d.Code);
|
|
Assert.Equal(string.Empty, d.Message);
|
|
}
|
|
|
|
[Fact]
|
|
public void MatchFound_EmptyPlayerList_RoundTrips()
|
|
{
|
|
var m = new MatchFoundMsg { RoomId = "r0", Version = 1, SelfPlayerId = 0 };
|
|
// Players 默认空列表,不添加任何玩家
|
|
var d = MatchFoundMsg.Decode(m.Encode());
|
|
Assert.Equal("r0", d.RoomId);
|
|
Assert.Equal(1, d.Version);
|
|
Assert.Equal(0, d.SelfPlayerId);
|
|
Assert.NotNull(d.Players);
|
|
Assert.Empty(d.Players);
|
|
}
|
|
}
|
|
}
|