From 61193643069dd382f2b2442863a12a30f4a14c59 Mon Sep 17 00:00:00 2001 From: Erik Date: Wed, 29 Jul 2026 01:54:56 +0200 Subject: [PATCH] test(net): pin the transport flag word against ACE, all twenty-three bits The wire-stack audit checked the transport layer by hand and found it clean: PacketHeader's seven fields match ACE's Pack order exactly, the optional-header sections are parsed in ACE's order, and PacketHeaderFlags is a twenty-three of twenty-three value match including the sparse gaps between 0x04 and 0x100 and between 0x00800000 and 0x01000000. Clean is worth freezing. These bits are not design choices; each one gates an optional-header section, so a single wrong value shifts every following section's offset and takes the packet checksum with it. The failure would not look like a wrong flag, it would look like a corrupt connection. The enum is small enough to pin exhaustively, so this transcribes ACE's declaration and asserts both directions: every ACE flag exists here with ACE's value, and we declare nothing ACE does not. Core.Net tests go 630 to 654. Co-Authored-By: Claude Fable 5 --- .../PacketHeaderFlagsConformanceTests.cs | 90 +++++++++++++++++++ 1 file changed, 90 insertions(+) create mode 100644 tests/AcDream.Core.Net.Tests/Packets/PacketHeaderFlagsConformanceTests.cs diff --git a/tests/AcDream.Core.Net.Tests/Packets/PacketHeaderFlagsConformanceTests.cs b/tests/AcDream.Core.Net.Tests/Packets/PacketHeaderFlagsConformanceTests.cs new file mode 100644 index 00000000..1144b1bf --- /dev/null +++ b/tests/AcDream.Core.Net.Tests/Packets/PacketHeaderFlagsConformanceTests.cs @@ -0,0 +1,90 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using AcDream.Core.Net.Packets; +using Xunit; + +namespace AcDream.Core.Net.Tests.Packets; + +/// +/// Value-conformance for the transport flag word against ACE's +/// Source/ACE.Server/Network/PacketHeaderFlags.cs, read 2026-07-29 +/// during the wire-stack audit. +/// +/// These are wire-format facts, not choices: a flag bit is the gate for +/// an optional-header section, so a single wrong value silently shifts every +/// subsequent section's offset and corrupts the packet checksum. The enum is +/// small enough to pin exhaustively, and doing so makes any future edit a +/// deliberate act rather than a typo. +/// +/// The audit found acdream's enum a 23-of-23 match with ACE's, including +/// the sparse gaps (nothing between 0x04 and 0x100, nothing between 0x00800000 +/// and 0x01000000). This test freezes that result. +/// +public class PacketHeaderFlagsConformanceTests +{ + /// + /// Transcribed from ACE's PacketHeaderFlags enum, in declaration order. + /// The trailing comments are ACE's own. + /// + private static readonly (string Name, uint Value)[] AceFlags = + { + ("None", 0x00000000u), + ("Retransmission", 0x00000001u), + ("EncryptedChecksum", 0x00000002u), // can't be paired with 0x1 + ("BlobFragments", 0x00000004u), + ("ServerSwitch", 0x00000100u), + ("LogonServerAddr", 0x00000200u), + ("EmptyHeader1", 0x00000400u), + ("Referral", 0x00000800u), + ("RequestRetransmit", 0x00001000u), // Nak + ("RejectRetransmit", 0x00002000u), // Empty Ack + ("AckSequence", 0x00004000u), // Pak + ("Disconnect", 0x00008000u), // Empty Header 2 + ("LoginRequest", 0x00010000u), + ("WorldLoginRequest", 0x00020000u), + ("ConnectRequest", 0x00040000u), + ("ConnectResponse", 0x00080000u), + ("NetError", 0x00100000u), + ("NetErrorDisconnect", 0x00200000u), + ("CICMDCommand", 0x00400000u), + ("TimeSync", 0x01000000u), + ("EchoRequest", 0x02000000u), + ("EchoResponse", 0x04000000u), + ("Flow", 0x08000000u), + }; + + public static TheoryData Flags() + { + var data = new TheoryData(); + foreach ((string name, uint value) in AceFlags) + data.Add(name, value); + return data; + } + + [Theory] + [MemberData(nameof(Flags))] + public void Flag_MatchesAceValue(string name, uint aceValue) + { + Assert.True( + Enum.IsDefined(typeof(PacketHeaderFlags), aceValue) || aceValue == 0, + $"ACE declares {name} = 0x{aceValue:X8}; acdream has no such value."); + + object parsed = Enum.Parse(typeof(PacketHeaderFlags), name); + Assert.Equal(aceValue, (uint)(PacketHeaderFlags)parsed); + } + + [Fact] + public void EnumHasNoMembersAceDoesNotDeclare() + { + HashSet ace = AceFlags.Select(f => f.Name).ToHashSet(StringComparer.Ordinal); + string[] ours = Enum.GetNames(typeof(PacketHeaderFlags)); + + string[] extra = ours.Where(n => !ace.Contains(n)).ToArray(); + + Assert.True( + extra.Length == 0, + $"acdream declares flags ACE does not: {string.Join(", ", extra)}"); + Assert.Equal(AceFlags.Length, ours.Length); + } +}