From d3767757313a2a3abb0fec141bf30f248caa4d6b Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 31 Aug 2025 05:15:08 +0000 Subject: [PATCH] Add comprehensive mail bitstream tests starting with MailInfo serialization Co-authored-by: aronwk-aaron <26027722+aronwk-aaron@users.noreply.github.com> --- tests/dNetTests/CMakeLists.txt | 1 + tests/dNetTests/MailBitStreamTests.cpp | 269 +++++++++++++++++++++++++ 2 files changed, 270 insertions(+) create mode 100644 tests/dNetTests/MailBitStreamTests.cpp diff --git a/tests/dNetTests/CMakeLists.txt b/tests/dNetTests/CMakeLists.txt index fa7d40a2..eeb3e7c2 100644 --- a/tests/dNetTests/CMakeLists.txt +++ b/tests/dNetTests/CMakeLists.txt @@ -5,6 +5,7 @@ set(DNETTESTS_SOURCES "WorldPacketTests.cpp" "MasterPacketTests.cpp" "PacketEdgeCaseTests.cpp" + "MailBitStreamTests.cpp" ) # Set our executable diff --git a/tests/dNetTests/MailBitStreamTests.cpp b/tests/dNetTests/MailBitStreamTests.cpp new file mode 100644 index 00000000..c6442f25 --- /dev/null +++ b/tests/dNetTests/MailBitStreamTests.cpp @@ -0,0 +1,269 @@ +#include "TestCommon.h" +#include "MailInfo.h" +#include "dCommonVars.h" + +class MailBitStreamTests : public PacketTestsBase { +protected: + void SetUp() override { + PacketTestsBase::SetUp(); + } + + void TearDown() override { + PacketTestsBase::TearDown(); + } + + /** + * Helper to create a sample MailInfo for testing + */ + MailInfo CreateSampleMailInfo() { + MailInfo mailInfo; + mailInfo.senderUsername = "TestSender"; + mailInfo.recipient = "TestRecipient"; + mailInfo.subject = "Test Subject"; + mailInfo.body = "Test body message"; + mailInfo.id = 12345; + mailInfo.senderId = 67890; + mailInfo.receiverId = 11111; + mailInfo.timeSent = 1234567890; + mailInfo.wasRead = false; + mailInfo.languageCode = 1033; + mailInfo.itemID = LWOOBJID_EMPTY; + mailInfo.itemCount = 0; + mailInfo.itemLOT = LOT_NULL; + mailInfo.itemSubkey = LWOOBJID_EMPTY; + return mailInfo; + } +}; + +// Test basic MailInfo serialization +TEST_F(MailBitStreamTests, MailInfoBasicSerialization) { + MailInfo originalMail = CreateSampleMailInfo(); + + RakNet::BitStream outStream; + originalMail.Serialize(outStream); + + // Verify the serialized data structure - basic sanity check + ASSERT_GT(outStream.GetNumberOfBytesUsed(), 0); + + // MailInfo serialization includes id, subject, body, sender, and various item data + // Let's verify the first field (id) is written correctly + outStream.ResetReadPointer(); + + uint64_t readId; + outStream.Read(readId); + ASSERT_EQ(readId, originalMail.id); +} + +// Test MailInfo serialization with item attachment +TEST_F(MailBitStreamTests, MailInfoWithAttachmentSerialization) { + MailInfo originalMail = CreateSampleMailInfo(); + originalMail.itemID = 999888777; + originalMail.itemCount = 5; + originalMail.itemLOT = 1234; + originalMail.itemSubkey = 555444333; + + RakNet::BitStream outStream; + originalMail.Serialize(outStream); + + // Verify the serialized data includes all our data + ASSERT_GT(outStream.GetNumberOfBytesUsed(), 0); + + // Reset and verify id + outStream.ResetReadPointer(); + uint64_t readId; + outStream.Read(readId); + ASSERT_EQ(readId, originalMail.id); +} + +// Test MailInfo serialization with different attachment scenarios +TEST_F(MailBitStreamTests, MailInfoVariousAttachmentScenarios) { + // Test with no attachment + { + MailInfo noAttachment = CreateSampleMailInfo(); + noAttachment.itemID = LWOOBJID_EMPTY; + noAttachment.itemCount = 0; + noAttachment.itemLOT = LOT_NULL; + noAttachment.itemSubkey = LWOOBJID_EMPTY; + + RakNet::BitStream outStream; + noAttachment.Serialize(outStream); + + ASSERT_GT(outStream.GetNumberOfBytesUsed(), 0); + outStream.ResetReadPointer(); + uint64_t readId; + outStream.Read(readId); + ASSERT_EQ(readId, noAttachment.id); + } + + // Test with attachment + { + MailInfo withAttachment = CreateSampleMailInfo(); + withAttachment.itemID = 123456789; + withAttachment.itemCount = 5; + withAttachment.itemLOT = 9876; + withAttachment.itemSubkey = 555666777; + + RakNet::BitStream outStream; + withAttachment.Serialize(outStream); + + ASSERT_GT(outStream.GetNumberOfBytesUsed(), 0); + outStream.ResetReadPointer(); + uint64_t readId; + outStream.Read(readId); + ASSERT_EQ(readId, withAttachment.id); + } +} + +// Test MailInfo serialization consistency +TEST_F(MailBitStreamTests, MailInfoSerializationConsistency) { + MailInfo originalMail = CreateSampleMailInfo(); + originalMail.itemID = 111222333; + originalMail.itemCount = 7; + originalMail.itemLOT = 5678; + originalMail.itemSubkey = 444555666; + + // Serialize the same mail multiple times + RakNet::BitStream stream1, stream2, stream3; + + originalMail.Serialize(stream1); + originalMail.Serialize(stream2); + originalMail.Serialize(stream3); + + // All streams should have the same number of bytes + ASSERT_EQ(stream1.GetNumberOfBytesUsed(), stream2.GetNumberOfBytesUsed()); + ASSERT_EQ(stream2.GetNumberOfBytesUsed(), stream3.GetNumberOfBytesUsed()); + + // And the same data content + std::vector data1(stream1.GetNumberOfBytesUsed()); + std::vector data2(stream2.GetNumberOfBytesUsed()); + std::vector data3(stream3.GetNumberOfBytesUsed()); + + memcpy(data1.data(), stream1.GetData(), stream1.GetNumberOfBytesUsed()); + memcpy(data2.data(), stream2.GetData(), stream2.GetNumberOfBytesUsed()); + memcpy(data3.data(), stream3.GetData(), stream3.GetNumberOfBytesUsed()); + + ASSERT_EQ(data1, data2); + ASSERT_EQ(data2, data3); +} + +// Test MailInfo with Unicode characters +TEST_F(MailBitStreamTests, MailInfoUnicodeHandling) { + MailInfo originalMail = CreateSampleMailInfo(); + originalMail.subject = "テストメール"; // "Test Mail" in Japanese + originalMail.body = "これはテストメッセージです。"; // "This is a test message" in Japanese + originalMail.senderUsername = "プレイヤー1"; // "Player 1" in Japanese + + RakNet::BitStream outStream; + originalMail.Serialize(outStream); + + // Verify data was written + ASSERT_GT(outStream.GetNumberOfBytesUsed(), 0); + + // Since we can't easily deserialize (it doesn't read all fields), + // we just verify that Unicode content can be serialized without errors + outStream.ResetReadPointer(); + uint64_t readId; + outStream.Read(readId); + ASSERT_EQ(readId, originalMail.id); +} + +// Test MailInfo edge cases with special values +TEST_F(MailBitStreamTests, MailInfoEdgeCases) { + MailInfo originalMail = CreateSampleMailInfo(); + + // Test with special/edge case values + originalMail.id = 0; // Zero ID + originalMail.itemID = LWOOBJID_EMPTY; // Special empty value + originalMail.itemCount = -1; // Negative count + originalMail.itemLOT = LOT_NULL; // Null LOT + originalMail.timeSent = 0; // Zero time + + RakNet::BitStream outStream; + originalMail.Serialize(outStream); + + ASSERT_GT(outStream.GetNumberOfBytesUsed(), 0); + + // Verify the ID field + outStream.ResetReadPointer(); + uint64_t readId; + outStream.Read(readId); + ASSERT_EQ(readId, 0); +} + +// Test MailInfo with very long strings that get truncated +TEST_F(MailBitStreamTests, MailInfoStringTruncation) { + MailInfo originalMail = CreateSampleMailInfo(); + + // Create strings longer than the allowed maximums + originalMail.subject = std::string(100, 'S'); // Longer than 50 char limit + originalMail.body = std::string(500, 'B'); // Longer than 400 char limit + originalMail.senderUsername = std::string(50, 'U'); // Longer than 32 char limit + + RakNet::BitStream outStream; + originalMail.Serialize(outStream); + + // Should still serialize successfully (LUWString handles truncation) + ASSERT_GT(outStream.GetNumberOfBytesUsed(), 0); + + outStream.ResetReadPointer(); + uint64_t readId; + outStream.Read(readId); + ASSERT_EQ(readId, originalMail.id); +} + +// Test MailInfo data integrity across field types +TEST_F(MailBitStreamTests, MailInfoDataTypeIntegrity) { + MailInfo originalMail = CreateSampleMailInfo(); + + // Test with specific values to verify data types are handled correctly + originalMail.id = 0xFFFFFFFFFFFFFFFF; // Max uint64_t + originalMail.senderId = 0xFFFFFFFF; // Max uint32_t + originalMail.receiverId = 0xFFFFFFFF; // Max uint32_t + originalMail.timeSent = 0xFFFFFFFFFFFFFFFF; // Max uint64_t + originalMail.wasRead = true; + originalMail.languageCode = 0xFFFF; // Max uint16_t + originalMail.itemID = 0xFFFFFFFFFFFFFFFF; // Max LWOOBJID + originalMail.itemCount = 32767; // Max int16_t positive value + originalMail.itemSubkey = 0xFFFFFFFFFFFFFFFF; // Max LWOOBJID + + RakNet::BitStream outStream; + originalMail.Serialize(outStream); + + ASSERT_GT(outStream.GetNumberOfBytesUsed(), 0); + + // Verify the first field (id) + outStream.ResetReadPointer(); + uint64_t readId; + outStream.Read(readId); + ASSERT_EQ(readId, 0xFFFFFFFFFFFFFFFF); +} + +// Test MailInfo with empty/minimal data +TEST_F(MailBitStreamTests, MailInfoMinimalData) { + MailInfo minimalMail; + // Set only required/essential fields + minimalMail.id = 1; + minimalMail.subject = ""; + minimalMail.body = ""; + minimalMail.senderUsername = ""; + minimalMail.recipient = ""; + minimalMail.senderId = 0; + minimalMail.receiverId = 0; + minimalMail.timeSent = 0; + minimalMail.wasRead = false; + minimalMail.languageCode = 0; + minimalMail.itemID = 0; + minimalMail.itemCount = 0; + minimalMail.itemLOT = 0; + minimalMail.itemSubkey = 0; + + RakNet::BitStream outStream; + minimalMail.Serialize(outStream); + + ASSERT_GT(outStream.GetNumberOfBytesUsed(), 0); + + outStream.ResetReadPointer(); + uint64_t readId; + outStream.Read(readId); + ASSERT_EQ(readId, 1); +} \ No newline at end of file