using System; using Xunit; using XWorld.Framework.Protocol; namespace XWorld.Framework.Tests { public class PacketCodecTests { [Theory] [InlineData(0u)] [InlineData(1u)] [InlineData(127u)] [InlineData(128u)] [InlineData(16384u)] [InlineData(uint.MaxValue)] public void VarUInt_RoundTrips(uint value) { var w = new PacketWriter(); w.WriteVarUInt(value); var r = new PacketReader(w.ToArray()); Assert.Equal(value, r.ReadVarUInt()); Assert.False(r.HasMore); } [Theory] [InlineData(0)] [InlineData(1)] [InlineData(-1)] [InlineData(int.MaxValue)] [InlineData(int.MinValue)] public void VarInt_RoundTrips(int value) { var w = new PacketWriter(); w.WriteVarInt(value); var r = new PacketReader(w.ToArray()); Assert.Equal(value, r.ReadVarInt()); } [Theory] [InlineData(0L)] [InlineData(-1234567890123L)] [InlineData(long.MaxValue)] [InlineData(long.MinValue)] public void VarLong_RoundTrips(long value) { var w = new PacketWriter(); w.WriteVarLong(value); var r = new PacketReader(w.ToArray()); Assert.Equal(value, r.ReadVarLong()); } [Fact] public void MixedSequence_RoundTrips_InOrder() { var w = new PacketWriter(); w.WriteBool(true); w.WriteByte(200); w.WriteUInt16(50000); w.WriteVarInt(-42); w.WriteSingle(3.14159f); w.WriteString("héllo 世界"); w.WriteBytes(new byte[] { 1, 2, 3, 0, 255 }); var r = new PacketReader(w.ToArray()); Assert.True(r.ReadBool()); Assert.Equal((byte)200, r.ReadByte()); Assert.Equal((ushort)50000, r.ReadUInt16()); Assert.Equal(-42, r.ReadVarInt()); Assert.Equal(3.14159f, r.ReadSingle(), 5); Assert.Equal("héllo 世界", r.ReadString()); Assert.Equal(new byte[] { 1, 2, 3, 0, 255 }, r.ReadBytes()); Assert.False(r.HasMore); } [Fact] public void EmptyAndNull_String_Bytes_RoundTripAsEmpty() { var w = new PacketWriter(); w.WriteString(null); w.WriteString(""); w.WriteBytes(null); w.WriteBytes(Array.Empty()); var r = new PacketReader(w.ToArray()); Assert.Equal("", r.ReadString()); Assert.Equal("", r.ReadString()); Assert.Empty(r.ReadBytes()); Assert.Empty(r.ReadBytes()); } [Fact] public void ReadPastEnd_Throws() { var r = new PacketReader(Array.Empty()); Assert.Throws(() => r.ReadByte()); } [Fact] public void ReadBytes_WithBogusLength_Throws() { // 长度前缀声称 10 字节,实际无数据 var w = new PacketWriter(); w.WriteVarUInt(10); var r = new PacketReader(w.ToArray()); Assert.Throws(() => r.ReadBytes()); } [Fact] public void ReadVarUInt_SixthByte_Throws() { // 5 个延续字节后还有第 6 字节 → 过长,必须抛异常而非静默损坏 var r = new PacketReader(new byte[] { 0xFF, 0xFF, 0xFF, 0xFF, 0x8F, 0x00 }); Assert.Throws(() => r.ReadVarUInt()); } [Fact] public void ReadVarUInt_LastByteOverflow_Throws() { // 第 5 字节 0x10 表示值超过 uint.MaxValue var r = new PacketReader(new byte[] { 0xFF, 0xFF, 0xFF, 0xFF, 0x10 }); Assert.Throws(() => r.ReadVarUInt()); } [Fact] public void ReadVarLong_EleventhByte_Throws() { var r = new PacketReader(new byte[] { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x81, 0x00 }); Assert.Throws(() => r.ReadVarLong()); } [Fact] public void ReadVarLong_LastByteOverflow_Throws() { // 第 10 字节 0x02 表示值超过 ulong 的 64 位 var r = new PacketReader(new byte[] { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x02 }); Assert.Throws(() => r.ReadVarLong()); } } }