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>
This commit is contained in:
copilot-swe-agent[bot]
2025-08-31 04:44:51 +00:00
parent a82aeec50e
commit 90f325f59c

View File

@@ -17,6 +17,7 @@
#include "MessageType/Chat.h" #include "MessageType/Chat.h"
#include "MessageType/Client.h" #include "MessageType/Client.h"
#include "MessageType/Master.h" #include "MessageType/Master.h"
#include "eRenameResponse.h"
// Game dependencies for mocking // Game dependencies for mocking
#include "Game.h" #include "Game.h"
@@ -237,21 +238,30 @@ TEST_F(PacketTests, ChatAnnouncementSerialization) {
announcement.title = "Test Title"; announcement.title = "Test Title";
announcement.message = "Test announcement message"; announcement.message = "Test announcement message";
RakNet::BitStream bitStream; // Call Send which will add header and serialize
announcement.Serialize(bitStream); announcement.Send(UNASSIGNED_SYSTEM_ADDRESS);
VerifyHeader(&bitStream, ServiceType::CHAT, static_cast<uint32_t>(MessageType::Chat::GM_ANNOUNCE)); auto* bitStream = GetMostRecentBitStream();
VerifyHeader(bitStream, ServiceType::CHAT, static_cast<uint32_t>(MessageType::Chat::GM_ANNOUNCE));
// Read announcement data // Read announcement data (size prefixed strings)
LUString readTitle; uint32_t titleSize;
LUString readMessage; bitStream->Read(titleSize);
ASSERT_EQ(titleSize, announcement.title.size());
bitStream.Read(readTitle); std::string readTitle(titleSize, '\0');
bitStream.Read(readMessage); bitStream->ReadBits(reinterpret_cast<unsigned char*>(readTitle.data()), BYTES_TO_BITS(titleSize), true);
ASSERT_EQ(readTitle.string, "Test Title"); uint32_t messageSize;
ASSERT_EQ(readMessage.string, "Test announcement message"); bitStream->Read(messageSize);
ASSERT_EQ(bitStream.GetNumberOfUnreadBits(), 0); ASSERT_EQ(messageSize, announcement.message.size());
std::string readMessage(messageSize, '\0');
bitStream->ReadBits(reinterpret_cast<unsigned char*>(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) { TEST_F(PacketTests, ChatAchievementNotifySerialization) {
@@ -261,27 +271,43 @@ TEST_F(PacketTests, ChatAchievementNotifySerialization) {
notify.earningPlayerID = 987654321; notify.earningPlayerID = 987654321;
notify.earnerName = LUWString(u"EarnerPlayer"); notify.earnerName = LUWString(u"EarnerPlayer");
RakNet::BitStream bitStream; // Call Send which will add header and serialize
notify.Serialize(bitStream); notify.Send(UNASSIGNED_SYSTEM_ADDRESS);
VerifyHeader(&bitStream, ServiceType::CHAT, static_cast<uint32_t>(MessageType::Chat::ACHIEVEMENT_NOTIFY)); auto* bitStream = GetMostRecentBitStream();
VerifyHeader(bitStream, ServiceType::CHAT, static_cast<uint32_t>(MessageType::Chat::ACHIEVEMENT_NOTIFY));
// Read achievement data // Read achievement data based on actual Serialize implementation
LUWString readTargetPlayerName; // 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; uint32_t readMissionEmailID;
LWOOBJID readEarningPlayerID; LWOOBJID readEarningPlayerID;
LUWString readEarnerName; LUWString readTargetPlayerName;
bitStream.Read(readTargetPlayerName); bitStream->Read(packing1);
bitStream.Read(readMissionEmailID); bitStream->Read(packing2);
bitStream.Read(readEarningPlayerID); bitStream->Read(packing3);
bitStream.Read(readEarnerName); 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(readMissionEmailID, 12345u);
ASSERT_EQ(readEarningPlayerID, 987654321); ASSERT_EQ(readEarningPlayerID, 987654321);
ASSERT_EQ(readEarnerName.string, u"EarnerPlayer"); ASSERT_EQ(readTargetPlayerName.string, u"TargetPlayer");
ASSERT_EQ(bitStream.GetNumberOfUnreadBits(), 0); ASSERT_EQ(bitStream->GetNumberOfUnreadBits(), 0);
} }
TEST_F(PacketTests, ChatTeamInviteInitialResponseSerialization) { TEST_F(PacketTests, ChatTeamInviteInitialResponseSerialization) {
@@ -289,21 +315,22 @@ TEST_F(PacketTests, ChatTeamInviteInitialResponseSerialization) {
response.inviteFailedToSend = true; response.inviteFailedToSend = true;
response.playerName = LUWString(u"InviteePlayer"); response.playerName = LUWString(u"InviteePlayer");
RakNet::BitStream bitStream; // Call Send which will add header and serialize
response.Serialize(bitStream); response.Send(UNASSIGNED_SYSTEM_ADDRESS);
VerifyHeader(&bitStream, ServiceType::CLIENT, static_cast<uint32_t>(MessageType::Client::TEAM_INVITE_INITIAL_RESPONSE)); auto* bitStream = GetMostRecentBitStream();
VerifyHeader(bitStream, ServiceType::CLIENT, static_cast<uint32_t>(MessageType::Client::TEAM_INVITE_INITIAL_RESPONSE));
// Read team invite response data // Read team invite response data
bool readInviteFailedToSend; uint8_t readInviteFailedToSend; // Written as uint8_t in actual implementation
LUWString readPlayerName; LUWString readPlayerName;
bitStream.Read(readInviteFailedToSend); bitStream->Read(readInviteFailedToSend);
bitStream.Read(readPlayerName); bitStream->Read(readPlayerName);
ASSERT_EQ(readInviteFailedToSend, true); ASSERT_EQ(readInviteFailedToSend, static_cast<uint8_t>(true));
ASSERT_EQ(readPlayerName.string, u"InviteePlayer"); ASSERT_EQ(readPlayerName.string, u"InviteePlayer");
ASSERT_EQ(bitStream.GetNumberOfUnreadBits(), 0); ASSERT_EQ(bitStream->GetNumberOfUnreadBits(), 0);
} }
// ===== WorldPackets Tests ===== // ===== WorldPackets Tests =====
@@ -387,24 +414,24 @@ TEST_F(PacketTests, MasterZoneTransferResponseStructure) {
uint32_t readZoneID; uint32_t readZoneID;
uint32_t readZoneInstance; uint32_t readZoneInstance;
uint32_t readZoneClone; uint32_t readZoneClone;
LUString readServerIP; uint16_t readServerPort; // Note: written as uint16_t in actual implementation
uint32_t readServerPort; LUString readServerIP(255); // Note: written as LUString with size 255
bitStream->Read(readRequestID); bitStream->Read(readRequestID);
bitStream->Read(readMythranShift); bitStream->Read(readMythranShift);
bitStream->Read(readZoneID); bitStream->Read(readZoneID);
bitStream->Read(readZoneInstance); bitStream->Read(readZoneInstance);
bitStream->Read(readZoneClone); bitStream->Read(readZoneClone);
bitStream->Read(readServerIP);
bitStream->Read(readServerPort); bitStream->Read(readServerPort);
bitStream->Read(readServerIP);
ASSERT_EQ(readRequestID, testRequestID); ASSERT_EQ(readRequestID, testRequestID);
ASSERT_EQ(readMythranShift, static_cast<uint8_t>(testMythranShift)); ASSERT_EQ(readMythranShift, static_cast<uint8_t>(testMythranShift));
ASSERT_EQ(readZoneID, testZoneID); ASSERT_EQ(readZoneID, testZoneID);
ASSERT_EQ(readZoneInstance, testZoneInstance); ASSERT_EQ(readZoneInstance, testZoneInstance);
ASSERT_EQ(readZoneClone, testZoneClone); ASSERT_EQ(readZoneClone, testZoneClone);
ASSERT_EQ(readServerPort, static_cast<uint16_t>(testServerPort));
ASSERT_EQ(readServerIP.string, testServerIP); ASSERT_EQ(readServerIP.string, testServerIP);
ASSERT_EQ(readServerPort, testServerPort);
ASSERT_EQ(bitStream->GetNumberOfUnreadBits(), 0); ASSERT_EQ(bitStream->GetNumberOfUnreadBits(), 0);
} }
@@ -499,3 +526,127 @@ TEST_F(PacketTests, LongPasswordHandling) {
ASSERT_EQ(readSupportsObjects, 1); ASSERT_EQ(readSupportsObjects, 1);
ASSERT_EQ(bitStream.GetNumberOfUnreadBits(), 0); 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<uint32_t>(MessageType::Client::DELETE_CHARACTER_RESPONSE));
uint8_t readResponse;
bitStream->Read(readResponse);
ASSERT_EQ(readResponse, static_cast<uint8_t>(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<uint32_t>(MessageType::Client::CHARACTER_RENAME_RESPONSE));
uint8_t readResponse;
bitStream->Read(readResponse);
ASSERT_EQ(readResponse, static_cast<uint8_t>(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<uint32_t>(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<uint16_t>(testServerPort));
ASSERT_EQ(readMythranShift, static_cast<uint8_t>(testMythranShift));
ASSERT_EQ(bitStream->GetNumberOfUnreadBits(), 0);
}
TEST_F(PacketTests, WorldServerState) {
WorldPackets::SendServerState(UNASSIGNED_SYSTEM_ADDRESS);
auto* bitStream = GetMostRecentBitStream();
VerifyHeader(bitStream, ServiceType::CLIENT, static_cast<uint32_t>(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);
}