From 90f325f59c3567499b76d8ababaedccf1e1d8af9 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 31 Aug 2025 04:44:51 +0000 Subject: [PATCH] Complete comprehensive packet testing framework with 20 tests covering all major packet types and edge cases Co-authored-by: aronwk-aaron <26027722+aronwk-aaron@users.noreply.github.com> --- tests/dNetTests/PacketTests.cpp | 225 ++++++++++++++++++++++++++------ 1 file changed, 188 insertions(+), 37 deletions(-) diff --git a/tests/dNetTests/PacketTests.cpp b/tests/dNetTests/PacketTests.cpp index e5bce3a4..383c8a86 100644 --- a/tests/dNetTests/PacketTests.cpp +++ b/tests/dNetTests/PacketTests.cpp @@ -17,6 +17,7 @@ #include "MessageType/Chat.h" #include "MessageType/Client.h" #include "MessageType/Master.h" +#include "eRenameResponse.h" // Game dependencies for mocking #include "Game.h" @@ -237,21 +238,30 @@ TEST_F(PacketTests, ChatAnnouncementSerialization) { announcement.title = "Test Title"; announcement.message = "Test announcement message"; - RakNet::BitStream bitStream; - announcement.Serialize(bitStream); + // Call Send which will add header and serialize + announcement.Send(UNASSIGNED_SYSTEM_ADDRESS); - VerifyHeader(&bitStream, ServiceType::CHAT, static_cast(MessageType::Chat::GM_ANNOUNCE)); + auto* bitStream = GetMostRecentBitStream(); + VerifyHeader(bitStream, ServiceType::CHAT, static_cast(MessageType::Chat::GM_ANNOUNCE)); - // Read announcement data - LUString readTitle; - LUString readMessage; + // Read announcement data (size prefixed strings) + uint32_t titleSize; + bitStream->Read(titleSize); + ASSERT_EQ(titleSize, announcement.title.size()); - bitStream.Read(readTitle); - bitStream.Read(readMessage); + std::string readTitle(titleSize, '\0'); + bitStream->ReadBits(reinterpret_cast(readTitle.data()), BYTES_TO_BITS(titleSize), true); - ASSERT_EQ(readTitle.string, "Test Title"); - ASSERT_EQ(readMessage.string, "Test announcement message"); - ASSERT_EQ(bitStream.GetNumberOfUnreadBits(), 0); + uint32_t messageSize; + bitStream->Read(messageSize); + ASSERT_EQ(messageSize, announcement.message.size()); + + std::string readMessage(messageSize, '\0'); + bitStream->ReadBits(reinterpret_cast(readMessage.data()), BYTES_TO_BITS(messageSize), true); + + ASSERT_EQ(readTitle, "Test Title"); + ASSERT_EQ(readMessage, "Test announcement message"); + ASSERT_EQ(bitStream->GetNumberOfUnreadBits(), 0); } TEST_F(PacketTests, ChatAchievementNotifySerialization) { @@ -261,27 +271,43 @@ TEST_F(PacketTests, ChatAchievementNotifySerialization) { notify.earningPlayerID = 987654321; notify.earnerName = LUWString(u"EarnerPlayer"); - RakNet::BitStream bitStream; - notify.Serialize(bitStream); + // Call Send which will add header and serialize + notify.Send(UNASSIGNED_SYSTEM_ADDRESS); - VerifyHeader(&bitStream, ServiceType::CHAT, static_cast(MessageType::Chat::ACHIEVEMENT_NOTIFY)); + auto* bitStream = GetMostRecentBitStream(); + VerifyHeader(bitStream, ServiceType::CHAT, static_cast(MessageType::Chat::ACHIEVEMENT_NOTIFY)); - // Read achievement data - LUWString readTargetPlayerName; + // Read achievement data based on actual Serialize implementation + // Order: packing(13), earnerName, packing(15), missionEmailID, earningPlayerID, targetPlayerName + uint64_t packing1; + uint32_t packing2; + uint8_t packing3; + LUWString readEarnerName; + uint64_t packing4; + uint32_t packing5; + uint16_t packing6; + uint8_t packing7; uint32_t readMissionEmailID; LWOOBJID readEarningPlayerID; - LUWString readEarnerName; + LUWString readTargetPlayerName; - bitStream.Read(readTargetPlayerName); - bitStream.Read(readMissionEmailID); - bitStream.Read(readEarningPlayerID); - bitStream.Read(readEarnerName); + bitStream->Read(packing1); + bitStream->Read(packing2); + bitStream->Read(packing3); + bitStream->Read(readEarnerName); + bitStream->Read(packing4); + bitStream->Read(packing5); + bitStream->Read(packing6); + bitStream->Read(packing7); + bitStream->Read(readMissionEmailID); + bitStream->Read(readEarningPlayerID); + bitStream->Read(readTargetPlayerName); - ASSERT_EQ(readTargetPlayerName.string, u"TargetPlayer"); + ASSERT_EQ(readEarnerName.string, u"EarnerPlayer"); ASSERT_EQ(readMissionEmailID, 12345u); ASSERT_EQ(readEarningPlayerID, 987654321); - ASSERT_EQ(readEarnerName.string, u"EarnerPlayer"); - ASSERT_EQ(bitStream.GetNumberOfUnreadBits(), 0); + ASSERT_EQ(readTargetPlayerName.string, u"TargetPlayer"); + ASSERT_EQ(bitStream->GetNumberOfUnreadBits(), 0); } TEST_F(PacketTests, ChatTeamInviteInitialResponseSerialization) { @@ -289,21 +315,22 @@ TEST_F(PacketTests, ChatTeamInviteInitialResponseSerialization) { response.inviteFailedToSend = true; response.playerName = LUWString(u"InviteePlayer"); - RakNet::BitStream bitStream; - response.Serialize(bitStream); + // Call Send which will add header and serialize + response.Send(UNASSIGNED_SYSTEM_ADDRESS); - VerifyHeader(&bitStream, ServiceType::CLIENT, static_cast(MessageType::Client::TEAM_INVITE_INITIAL_RESPONSE)); + auto* bitStream = GetMostRecentBitStream(); + VerifyHeader(bitStream, ServiceType::CLIENT, static_cast(MessageType::Client::TEAM_INVITE_INITIAL_RESPONSE)); - // Read team invite response data - bool readInviteFailedToSend; + // Read team invite response data + uint8_t readInviteFailedToSend; // Written as uint8_t in actual implementation LUWString readPlayerName; - bitStream.Read(readInviteFailedToSend); - bitStream.Read(readPlayerName); + bitStream->Read(readInviteFailedToSend); + bitStream->Read(readPlayerName); - ASSERT_EQ(readInviteFailedToSend, true); + ASSERT_EQ(readInviteFailedToSend, static_cast(true)); ASSERT_EQ(readPlayerName.string, u"InviteePlayer"); - ASSERT_EQ(bitStream.GetNumberOfUnreadBits(), 0); + ASSERT_EQ(bitStream->GetNumberOfUnreadBits(), 0); } // ===== WorldPackets Tests ===== @@ -387,24 +414,24 @@ TEST_F(PacketTests, MasterZoneTransferResponseStructure) { uint32_t readZoneID; uint32_t readZoneInstance; uint32_t readZoneClone; - LUString readServerIP; - uint32_t readServerPort; + uint16_t readServerPort; // Note: written as uint16_t in actual implementation + LUString readServerIP(255); // Note: written as LUString with size 255 bitStream->Read(readRequestID); bitStream->Read(readMythranShift); bitStream->Read(readZoneID); bitStream->Read(readZoneInstance); bitStream->Read(readZoneClone); - bitStream->Read(readServerIP); bitStream->Read(readServerPort); + bitStream->Read(readServerIP); ASSERT_EQ(readRequestID, testRequestID); ASSERT_EQ(readMythranShift, static_cast(testMythranShift)); ASSERT_EQ(readZoneID, testZoneID); ASSERT_EQ(readZoneInstance, testZoneInstance); ASSERT_EQ(readZoneClone, testZoneClone); + ASSERT_EQ(readServerPort, static_cast(testServerPort)); ASSERT_EQ(readServerIP.string, testServerIP); - ASSERT_EQ(readServerPort, testServerPort); ASSERT_EQ(bitStream->GetNumberOfUnreadBits(), 0); } @@ -498,4 +525,128 @@ TEST_F(PacketTests, LongPasswordHandling) { ASSERT_EQ(readSupportsWho, 1); ASSERT_EQ(readSupportsObjects, 1); ASSERT_EQ(bitStream.GetNumberOfUnreadBits(), 0); +} + +// ===== Additional Comprehensive Tests ===== + +TEST_F(PacketTests, WorldCharacterDeleteResponse) { + bool testResponse = false; + + WorldPackets::SendCharacterDeleteResponse(UNASSIGNED_SYSTEM_ADDRESS, testResponse); + + auto* bitStream = GetMostRecentBitStream(); + VerifyHeader(bitStream, ServiceType::CLIENT, static_cast(MessageType::Client::DELETE_CHARACTER_RESPONSE)); + + uint8_t readResponse; + bitStream->Read(readResponse); + + ASSERT_EQ(readResponse, static_cast(testResponse)); + ASSERT_EQ(bitStream->GetNumberOfUnreadBits(), 0); +} + +TEST_F(PacketTests, WorldCharacterRenameResponse) { + // Test with different enum values for character rename response + WorldPackets::SendCharacterRenameResponse(UNASSIGNED_SYSTEM_ADDRESS, eRenameResponse::NAME_IN_USE); + + auto* bitStream = GetMostRecentBitStream(); + VerifyHeader(bitStream, ServiceType::CLIENT, static_cast(MessageType::Client::CHARACTER_RENAME_RESPONSE)); + + uint8_t readResponse; + bitStream->Read(readResponse); + + ASSERT_EQ(readResponse, static_cast(eRenameResponse::NAME_IN_USE)); + ASSERT_EQ(bitStream->GetNumberOfUnreadBits(), 0); +} + +TEST_F(PacketTests, WorldTransferToWorld) { + std::string testServerIP = "10.0.0.1"; + uint32_t testServerPort = 3000; + bool testMythranShift = false; + + WorldPackets::SendTransferToWorld(UNASSIGNED_SYSTEM_ADDRESS, testServerIP, testServerPort, testMythranShift); + + auto* bitStream = GetMostRecentBitStream(); + VerifyHeader(bitStream, ServiceType::CLIENT, static_cast(MessageType::Client::TRANSFER_TO_WORLD)); + + LUString readServerIP; + uint16_t readServerPort; + uint8_t readMythranShift; + + bitStream->Read(readServerIP); + bitStream->Read(readServerPort); + bitStream->Read(readMythranShift); + + ASSERT_EQ(readServerIP.string, testServerIP); + ASSERT_EQ(readServerPort, static_cast(testServerPort)); + ASSERT_EQ(readMythranShift, static_cast(testMythranShift)); + ASSERT_EQ(bitStream->GetNumberOfUnreadBits(), 0); +} + +TEST_F(PacketTests, WorldServerState) { + WorldPackets::SendServerState(UNASSIGNED_SYSTEM_ADDRESS); + + auto* bitStream = GetMostRecentBitStream(); + VerifyHeader(bitStream, ServiceType::CLIENT, static_cast(MessageType::Client::SERVER_STATES)); + + uint8_t readState; + bitStream->Read(readState); + + ASSERT_EQ(readState, 1); // Server is ready + ASSERT_EQ(bitStream->GetNumberOfUnreadBits(), 0); +} + +TEST_F(PacketTests, PacketDataConsistency) { + // Test that multiple calls produce identical results + Stamp stamp1(eStamps::PASSPORT_AUTH_START, 100, 2000000000); + Stamp stamp2(eStamps::PASSPORT_AUTH_START, 100, 2000000000); + + RakNet::BitStream stream1, stream2; + stamp1.Serialize(stream1); + stamp2.Serialize(stream2); + + // Should produce identical bit streams + ASSERT_EQ(stream1.GetNumberOfBitsUsed(), stream2.GetNumberOfBitsUsed()); + + // Read both streams and compare + eStamps type1, type2; + uint32_t value1, value2; + uint64_t timestamp1, timestamp2; + + stream1.Read(type1); + stream1.Read(value1); + stream1.Read(timestamp1); + + stream2.Read(type2); + stream2.Read(value2); + stream2.Read(timestamp2); + + ASSERT_EQ(type1, type2); + ASSERT_EQ(value1, value2); + ASSERT_EQ(timestamp1, timestamp2); +} + +TEST_F(PacketTests, UnicodeStringHandling) { + // Test with various Unicode characters + FindPlayerRequest request; + request.requestor = 12345; + request.playerName = LUWString(u"テストプレイヤー123"); // Japanese characters + + RakNet::BitStream bitStream; + request.Serialize(bitStream); + + // Skip header + uint8_t rakNetPacketId{}; + uint16_t serviceType{}; + uint32_t packetId{}; + uint8_t always0{}; + bitStream.Read(rakNetPacketId); + bitStream.Read(serviceType); + bitStream.Read(packetId); + bitStream.Read(always0); + + FindPlayerRequest deserialized; + deserialized.Deserialize(bitStream); + + ASSERT_EQ(deserialized.requestor, request.requestor); + ASSERT_EQ(deserialized.playerName.string, request.playerName.string); } \ No newline at end of file