using AcDream.Core.Net.Cryptography; using AcDream.Core.Net.Packets; namespace AcDream.Core.Net.Tests.Packets; public class PacketCodecEncodeTests { [Fact] public void Encode_Then_TryDecode_UnencryptedChecksum_RoundTrips() { // 4-byte ack sequence in the optional section, no fragments. byte[] body = new byte[4] { 0x78, 0x56, 0x34, 0x12 }; var header = new PacketHeader { Sequence = 7, Flags = PacketHeaderFlags.AckSequence, Id = 1, Time = 100, }; byte[] datagram = PacketCodec.Encode(header, body, outboundIsaac: null); var result = PacketCodec.TryDecode(datagram, inboundIsaac: null); Assert.Equal(PacketCodec.DecodeError.None, result.Error); Assert.Equal(0x12345678u, result.Packet!.Optional.AckSequence); } [Fact] public void Encode_DataSizeIsOverwritten_MatchesBodyLength() { // Caller sets DataSize to garbage; Encode should overwrite it with // the actual body length. var header = new PacketHeader { Flags = PacketHeaderFlags.AckSequence, DataSize = 9999 }; byte[] body = new byte[4]; byte[] datagram = PacketCodec.Encode(header, body, null); var parsed = PacketHeader.Unpack(datagram); Assert.Equal(4, parsed.DataSize); } [Fact] public void Encode_EncryptedChecksum_PairsWithDecodeUsingSameIsaac() { var seed = new byte[] { 0xAB, 0xCD, 0xEF, 0x01 }; var isaacSend = new IsaacRandom(seed); var isaacRecv = new IsaacRandom(seed); byte[] body = new byte[4] { 1, 2, 3, 4 }; var header = new PacketHeader { Flags = PacketHeaderFlags.AckSequence | PacketHeaderFlags.EncryptedChecksum, }; byte[] datagram = PacketCodec.Encode(header, body, isaacSend); var result = PacketCodec.TryDecode(datagram, isaacRecv); Assert.Equal(PacketCodec.DecodeError.None, result.Error); } [Fact] public void Encode_EncryptedChecksum_WithoutIsaac_Throws() { var header = new PacketHeader { Flags = PacketHeaderFlags.EncryptedChecksum }; Assert.Throws( () => PacketCodec.Encode(header, ReadOnlySpan.Empty, outboundIsaac: null)); } [Fact] public void Encode_LoginRequest_DecodableAndBodyRoundTrips() { // End-to-end that exercises the whole outbound pipeline we care // about for integration testing: build LoginRequest body → pack // into a Packet with the LoginRequest flag → send through Encode → // decode via TryDecode → re-parse the body back to credentials. byte[] loginPayload = LoginRequest.Build("testaccount", "testpassword", 42); var header = new PacketHeader { Flags = PacketHeaderFlags.LoginRequest }; byte[] datagram = PacketCodec.Encode(header, loginPayload, outboundIsaac: null); var decoded = PacketCodec.TryDecode(datagram, inboundIsaac: null); Assert.Equal(PacketCodec.DecodeError.None, decoded.Error); var parsed = LoginRequest.Parse(decoded.Packet!.BodyBytes); Assert.Equal("testaccount", parsed.Account); Assert.Equal("testpassword", parsed.Password); } [Fact] public void Encode_FragmentBodyWithBlobFragmentsFlag_DecodeRebuildsFragment() { // Build a fragment body (16-byte header + 3-byte payload), set // BlobFragments flag, encode, decode, verify fragment is intact. var fragHeader = new MessageFragmentHeader { Sequence = 1, Id = 0x80000001u, Count = 1, TotalSize = 19, Index = 0, Queue = 0, }; byte[] body = new byte[19]; fragHeader.Pack(body); body[16] = 0xAA; body[17] = 0xBB; body[18] = 0xCC; var header = new PacketHeader { Flags = PacketHeaderFlags.BlobFragments }; byte[] datagram = PacketCodec.Encode(header, body, null); var result = PacketCodec.TryDecode(datagram, null); Assert.Equal(PacketCodec.DecodeError.None, result.Error); Assert.Single(result.Packet!.Fragments); Assert.Equal(new byte[] { 0xAA, 0xBB, 0xCC }, result.Packet.Fragments[0].Payload); } }