From 856186636f612186867d3707c31e67f7f60680e5 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 31 Aug 2025 22:54:34 +0000 Subject: [PATCH] Continue adding component tests: AchievementVendor, Character, QuickBuild, Script, Skill, Vendor tests (compilation fixes needed) Co-authored-by: aronwk-aaron <26027722+aronwk-aaron@users.noreply.github.com> --- .../AchievementVendorComponentTests.cpp | 112 ++++++++ .../dComponentsTests/CMakeLists.txt | 6 + .../CharacterComponentTests.cpp | 243 ++++++++++++++++++ .../QuickBuildComponentTests.cpp | 159 ++++++++++++ .../dComponentsTests/ScriptComponentTests.cpp | 148 +++++++++++ .../dComponentsTests/SkillComponentTests.cpp | 102 ++++++++ .../dComponentsTests/VendorComponentTests.cpp | 166 ++++++++++++ 7 files changed, 936 insertions(+) create mode 100644 tests/dGameTests/dComponentsTests/AchievementVendorComponentTests.cpp create mode 100644 tests/dGameTests/dComponentsTests/CharacterComponentTests.cpp create mode 100644 tests/dGameTests/dComponentsTests/QuickBuildComponentTests.cpp create mode 100644 tests/dGameTests/dComponentsTests/ScriptComponentTests.cpp create mode 100644 tests/dGameTests/dComponentsTests/SkillComponentTests.cpp create mode 100644 tests/dGameTests/dComponentsTests/VendorComponentTests.cpp diff --git a/tests/dGameTests/dComponentsTests/AchievementVendorComponentTests.cpp b/tests/dGameTests/dComponentsTests/AchievementVendorComponentTests.cpp new file mode 100644 index 00000000..d937d076 --- /dev/null +++ b/tests/dGameTests/dComponentsTests/AchievementVendorComponentTests.cpp @@ -0,0 +1,112 @@ +#include + +#include "AchievementVendorComponent.h" +#include "Entity.h" +#include "BitStream.h" +#include "GameDependencies.h" +#include "MessageType/Game.h" + +class AchievementVendorComponentTest : public GameDependenciesTest { +protected: + void SetUp() override { + SetUpDependencies(); + } + + void TearDown() override { + TearDownDependencies(); + } +}; + +TEST_F(AchievementVendorComponentTest, Serialize) { + Entity testEntity(15, info); + // Test initial update + AchievementVendorComponent achievementVendorComponent(&testEntity); + + RakNet::BitStream bitStream; + achievementVendorComponent.Serialize(bitStream, true); + + // Read the data manually to validate serialization format + bitStream.ResetReadPointer(); + + bool hasVendorInfo; + ASSERT_TRUE(bitStream.Read(hasVendorInfo)); + EXPECT_TRUE(hasVendorInfo); // Should always be true for initial update + + bool hasStandardCostItems; + ASSERT_TRUE(bitStream.Read(hasStandardCostItems)); + EXPECT_TRUE(hasStandardCostItems); // Set by RefreshInventory + + bool hasMultiCostItems; + ASSERT_TRUE(bitStream.Read(hasMultiCostItems)); + EXPECT_FALSE(hasMultiCostItems); // Default state +} + +TEST_F(AchievementVendorComponentTest, SerializeRegularUpdate) { + Entity testEntity(15, info); + AchievementVendorComponent achievementVendorComponent(&testEntity); + + // Reset dirty flag by doing initial serialization + RakNet::BitStream initStream; + achievementVendorComponent.Serialize(initStream, true); + + // Test regular update with no changes + RakNet::BitStream bitStream; + achievementVendorComponent.Serialize(bitStream, false); + + bitStream.ResetReadPointer(); + + bool hasVendorInfo; + ASSERT_TRUE(bitStream.Read(hasVendorInfo)); + EXPECT_FALSE(hasVendorInfo); // No dirty flags, so no data +} + +TEST_F(AchievementVendorComponentTest, SerializeWithDirtyVendor) { + Entity testEntity(15, info); + AchievementVendorComponent achievementVendorComponent(&testEntity); + + // Reset dirty flag + RakNet::BitStream initStream; + achievementVendorComponent.Serialize(initStream, true); + + // Make vendor dirty by changing state + achievementVendorComponent.SetHasMultiCostItems(true); + + RakNet::BitStream bitStream; + achievementVendorComponent.Serialize(bitStream, false); + + bitStream.ResetReadPointer(); + + bool hasVendorInfo; + ASSERT_TRUE(bitStream.Read(hasVendorInfo)); + EXPECT_TRUE(hasVendorInfo); // Should be true due to dirty flag + + bool hasStandardCostItems; + ASSERT_TRUE(bitStream.Read(hasStandardCostItems)); + EXPECT_TRUE(hasStandardCostItems); + + bool hasMultiCostItems; + ASSERT_TRUE(bitStream.Read(hasMultiCostItems)); + EXPECT_TRUE(hasMultiCostItems); // Changed to true +} + +TEST_F(AchievementVendorComponentTest, SerializeAfterDirtyCleared) { + Entity testEntity(15, info); + AchievementVendorComponent achievementVendorComponent(&testEntity); + + // Make dirty + achievementVendorComponent.SetHasMultiCostItems(true); + + // Serialize once to clear dirty flag + RakNet::BitStream firstStream; + achievementVendorComponent.Serialize(firstStream, false); + + // Serialize again - should show no vendor info + RakNet::BitStream secondStream; + achievementVendorComponent.Serialize(secondStream, false); + + secondStream.ResetReadPointer(); + + bool hasVendorInfo; + ASSERT_TRUE(secondStream.Read(hasVendorInfo)); + EXPECT_FALSE(hasVendorInfo); // Dirty flag should be cleared +} \ No newline at end of file diff --git a/tests/dGameTests/dComponentsTests/CMakeLists.txt b/tests/dGameTests/dComponentsTests/CMakeLists.txt index 8499d4df..c560fdbf 100644 --- a/tests/dGameTests/dComponentsTests/CMakeLists.txt +++ b/tests/dGameTests/dComponentsTests/CMakeLists.txt @@ -1,8 +1,10 @@ set(DCOMPONENTS_TESTS + "AchievementVendorComponentTests.cpp" "ActivityComponentTests.cpp" "BaseCombatAIComponentTests.cpp" "BouncerComponentTests.cpp" "BuffComponentTests.cpp" + "CharacterComponentTests.cpp" "CollectibleComponentTests.cpp" "ControllablePhysicsComponentTests.cpp" "DestroyableComponentTests.cpp" @@ -15,10 +17,14 @@ set(DCOMPONENTS_TESTS "ModelComponentTests.cpp" "MovingPlatformComponentTests.cpp" "PetComponentTests.cpp" + "QuickBuildComponentTests.cpp" "RenderComponentTests.cpp" "SavingTests.cpp" + "ScriptComponentTests.cpp" "SimplePhysicsComponentTests.cpp" + "SkillComponentTests.cpp" "SwitchComponentTests.cpp" + "VendorComponentTests.cpp" ) # Get the folder name and prepend it to the files above diff --git a/tests/dGameTests/dComponentsTests/CharacterComponentTests.cpp b/tests/dGameTests/dComponentsTests/CharacterComponentTests.cpp new file mode 100644 index 00000000..e39714ed --- /dev/null +++ b/tests/dGameTests/dComponentsTests/CharacterComponentTests.cpp @@ -0,0 +1,243 @@ +#include + +#include "CharacterComponent.h" +#include "Entity.h" +#include "BitStream.h" +#include "GameDependencies.h" +#include "Character.h" +#include "User.h" +#include "eGameActivity.h" +#include "eGameMasterLevel.h" +#include "eLootSourceType.h" +#include "MessageType/Game.h" + +class CharacterComponentTest : public GameDependenciesTest { +protected: + void SetUp() override { + SetUpDependencies(); + + // Create a mock user and character + m_User = std::make_unique(UNASSIGNED_SYSTEM_ADDRESS, "TestUser", "TestPassword"); + + m_Character = std::make_unique(1, m_User.get()); + m_Character->SetCoins(1000, eLootSourceType::NONE); + + // Set character appearance + m_Character->SetHairColor(5); + m_Character->SetHairStyle(10); + m_Character->SetShirtColor(15); + m_Character->SetPantsColor(20); + m_Character->SetShirtStyle(25); + m_Character->SetEyebrows(30); + m_Character->SetEyes(35); + m_Character->SetMouth(40); + } + + void TearDown() override { + TearDownDependencies(); + } + + std::unique_ptr m_User; + std::unique_ptr m_Character; +}; + +TEST_F(CharacterComponentTest, SerializeInitialUpdate) { + Entity testEntity(15, info); + CharacterComponent characterComponent(&testEntity, m_Character.get(), UNASSIGNED_SYSTEM_ADDRESS); + + RakNet::BitStream bitStream; + characterComponent.Serialize(bitStream, true); + + // Read the data manually to validate serialization format + bitStream.ResetReadPointer(); + + // Claim codes (4 codes) + for (int i = 0; i < 4; i++) { + bool hasClaimCode; + ASSERT_TRUE(bitStream.Read(hasClaimCode)); + EXPECT_FALSE(hasClaimCode); // Default state + } + + // Character appearance + uint32_t hairColor; + ASSERT_TRUE(bitStream.Read(hairColor)); + EXPECT_EQ(hairColor, 5); + + uint32_t hairStyle; + ASSERT_TRUE(bitStream.Read(hairStyle)); + EXPECT_EQ(hairStyle, 10); + + uint32_t head; + ASSERT_TRUE(bitStream.Read(head)); + EXPECT_EQ(head, 0); // Default + + uint32_t shirtColor; + ASSERT_TRUE(bitStream.Read(shirtColor)); + EXPECT_EQ(shirtColor, 15); + + uint32_t pantsColor; + ASSERT_TRUE(bitStream.Read(pantsColor)); + EXPECT_EQ(pantsColor, 20); + + uint32_t shirtStyle; + ASSERT_TRUE(bitStream.Read(shirtStyle)); + EXPECT_EQ(shirtStyle, 25); + + uint32_t headColor; + ASSERT_TRUE(bitStream.Read(headColor)); + EXPECT_EQ(headColor, 0); // Default + + uint32_t eyebrows; + ASSERT_TRUE(bitStream.Read(eyebrows)); + EXPECT_EQ(eyebrows, 30); + + uint32_t eyes; + ASSERT_TRUE(bitStream.Read(eyes)); + EXPECT_EQ(eyes, 35); + + uint32_t mouth; + ASSERT_TRUE(bitStream.Read(mouth)); + EXPECT_EQ(mouth, 40); + + uint64_t accountID; + ASSERT_TRUE(bitStream.Read(accountID)); + EXPECT_EQ(accountID, 0); // Default since we can't set it directly + + uint64_t lastLogin; + ASSERT_TRUE(bitStream.Read(lastLogin)); + EXPECT_EQ(lastLogin, 0); // Default since we can't set it directly + + uint64_t propModLastDisplayTime; + ASSERT_TRUE(bitStream.Read(propModLastDisplayTime)); + EXPECT_EQ(propModLastDisplayTime, 0); + + uint64_t uscore; + ASSERT_TRUE(bitStream.Read(uscore)); + EXPECT_EQ(uscore, 0); // Default + + bool freeToPlay; + ASSERT_TRUE(bitStream.Read(freeToPlay)); + EXPECT_FALSE(freeToPlay); // Disabled in DLU + + // Stats (23 total statistics) + for (int i = 0; i < 23; i++) { + uint64_t stat; + ASSERT_TRUE(bitStream.Read(stat)); + EXPECT_EQ(stat, 0); // All default to 0 + } + + bool hasUnknownFlag; + ASSERT_TRUE(bitStream.Read(hasUnknownFlag)); + EXPECT_FALSE(hasUnknownFlag); // Always writes 0 + + bool isLanding; + ASSERT_TRUE(bitStream.Read(isLanding)); + EXPECT_FALSE(isLanding); // Default state +} + +TEST_F(CharacterComponentTest, SerializeRegularUpdate) { + Entity testEntity(15, info); + CharacterComponent characterComponent(&testEntity, m_Character.get(), UNASSIGNED_SYSTEM_ADDRESS); + + RakNet::BitStream bitStream; + characterComponent.Serialize(bitStream, false); + + bitStream.ResetReadPointer(); + + // Should only have the dirty flags + bool dirtyGMInfo; + ASSERT_TRUE(bitStream.Read(dirtyGMInfo)); + EXPECT_FALSE(dirtyGMInfo); // Default state + + bool dirtyCurrentActivity; + ASSERT_TRUE(bitStream.Read(dirtyCurrentActivity)); + EXPECT_FALSE(dirtyCurrentActivity); // Default state + + bool dirtySocialInfo; + ASSERT_TRUE(bitStream.Read(dirtySocialInfo)); + EXPECT_FALSE(dirtySocialInfo); // Default state +} + +TEST_F(CharacterComponentTest, SerializeWithDirtyGMInfo) { + Entity testEntity(15, info); + CharacterComponent characterComponent(&testEntity, m_Character.get(), UNASSIGNED_SYSTEM_ADDRESS); + + // Make GM info dirty + characterComponent.SetPvpEnabled(true); + characterComponent.SetGMLevel(eGameMasterLevel::JUNIOR_MODERATOR); + + RakNet::BitStream bitStream; + characterComponent.Serialize(bitStream, false); + + bitStream.ResetReadPointer(); + + bool dirtyGMInfo; + ASSERT_TRUE(bitStream.Read(dirtyGMInfo)); + EXPECT_TRUE(dirtyGMInfo); + + bool pvpEnabled; + ASSERT_TRUE(bitStream.Read(pvpEnabled)); + EXPECT_TRUE(pvpEnabled); + + bool isGM; + ASSERT_TRUE(bitStream.Read(isGM)); + EXPECT_TRUE(isGM); + + eGameMasterLevel gmLevel; + ASSERT_TRUE(bitStream.Read(gmLevel)); + EXPECT_EQ(gmLevel, eGameMasterLevel::JUNIOR_MODERATOR); + + bool editorEnabled; + ASSERT_TRUE(bitStream.Read(editorEnabled)); + EXPECT_FALSE(editorEnabled); // Default + + eGameMasterLevel editorLevel; + ASSERT_TRUE(bitStream.Read(editorLevel)); + EXPECT_EQ(editorLevel, eGameMasterLevel::JUNIOR_MODERATOR); // Same as GM level +} + +TEST_F(CharacterComponentTest, SerializeWithDirtyCurrentActivity) { + Entity testEntity(15, info); + CharacterComponent characterComponent(&testEntity, m_Character.get(), UNASSIGNED_SYSTEM_ADDRESS); + + // Set current activity + characterComponent.SetCurrentActivity(eGameActivity::QUICKBUILDING); + + RakNet::BitStream bitStream; + characterComponent.Serialize(bitStream, false); + + bitStream.ResetReadPointer(); + + bool dirtyGMInfo; + ASSERT_TRUE(bitStream.Read(dirtyGMInfo)); + EXPECT_FALSE(dirtyGMInfo); + + bool dirtyCurrentActivity; + ASSERT_TRUE(bitStream.Read(dirtyCurrentActivity)); + EXPECT_TRUE(dirtyCurrentActivity); + + eGameActivity currentActivity; + ASSERT_TRUE(bitStream.Read(currentActivity)); + EXPECT_EQ(currentActivity, eGameActivity::QUICKBUILDING); +} + +TEST_F(CharacterComponentTest, SerializeWithClaimCodes) { + Entity testEntity(15, info); + CharacterComponent characterComponent(&testEntity, m_Character.get(), UNASSIGNED_SYSTEM_ADDRESS); + + // Set some claim codes via character (need to access private members through Character class) + // This is more of a conceptual test since claim codes are loaded from XML + + RakNet::BitStream bitStream; + characterComponent.Serialize(bitStream, true); + + bitStream.ResetReadPointer(); + + // Verify claim codes are properly handled (even if they're default values) + for (int i = 0; i < 4; i++) { + bool hasClaimCode; + ASSERT_TRUE(bitStream.Read(hasClaimCode)); + // In default state, all claim codes should be 0/false + EXPECT_FALSE(hasClaimCode); + } +} \ No newline at end of file diff --git a/tests/dGameTests/dComponentsTests/QuickBuildComponentTests.cpp b/tests/dGameTests/dComponentsTests/QuickBuildComponentTests.cpp new file mode 100644 index 00000000..eb0095fa --- /dev/null +++ b/tests/dGameTests/dComponentsTests/QuickBuildComponentTests.cpp @@ -0,0 +1,159 @@ +#include + +#include "QuickBuildComponent.h" +#include "Entity.h" +#include "BitStream.h" +#include "GameDependencies.h" +#include "DestroyableComponent.h" + +class QuickBuildComponentTest : public GameDependenciesTest { +protected: + void SetUp() override { + SetUpDependencies(); + } + + void TearDown() override { + TearDownDependencies(); + } +}; + +TEST_F(QuickBuildComponentTest, SerializeInitialUpdateNoDestroyable) { + Entity testEntity(15, info); + // Create QuickBuild without Destroyable component + QuickBuildComponent quickBuildComponent(&testEntity); + + RakNet::BitStream bitStream; + quickBuildComponent.Serialize(bitStream, true); + + // Read the data manually to validate serialization format + bitStream.ResetReadPointer(); + + // When no destroyable component, writes specific pattern for initial update + bool flag1; + ASSERT_TRUE(bitStream.Read(flag1)); + EXPECT_FALSE(flag1); // First flag is false + + bool flag2; + ASSERT_TRUE(bitStream.Read(flag2)); + EXPECT_FALSE(flag2); // Second flag is false + + bool flag3; + ASSERT_TRUE(bitStream.Read(flag3)); + EXPECT_FALSE(flag3); // Third flag is false + + // ScriptedActivity section + bool hasScriptedActivity; + ASSERT_TRUE(bitStream.Read(hasScriptedActivity)); + EXPECT_TRUE(hasScriptedActivity); // Always writes 1 + + uint32_t builderCount; + ASSERT_TRUE(bitStream.Read(builderCount)); + EXPECT_EQ(builderCount, 0); // No builder initially +} + +TEST_F(QuickBuildComponentTest, SerializeRegularUpdateNoDestroyable) { + Entity testEntity(15, info); + QuickBuildComponent quickBuildComponent(&testEntity); + + RakNet::BitStream bitStream; + quickBuildComponent.Serialize(bitStream, false); + + bitStream.ResetReadPointer(); + + // Regular update without destroyable should only write specific flags + bool flag1; + ASSERT_TRUE(bitStream.Read(flag1)); + EXPECT_FALSE(flag1); + + bool flag2; + ASSERT_TRUE(bitStream.Read(flag2)); + EXPECT_FALSE(flag2); + + // ScriptedActivity section + bool hasScriptedActivity; + ASSERT_TRUE(bitStream.Read(hasScriptedActivity)); + EXPECT_TRUE(hasScriptedActivity); + + uint32_t builderCount; + ASSERT_TRUE(bitStream.Read(builderCount)); + EXPECT_EQ(builderCount, 0); +} + +TEST_F(QuickBuildComponentTest, SerializeWithDestroyableComponent) { + Entity testEntity(15, info); + + // Add a destroyable component first + DestroyableComponent* destroyableComponent = new DestroyableComponent(&testEntity); + testEntity.AddComponent(eReplicaComponentType::DESTROYABLE, destroyableComponent); + + QuickBuildComponent quickBuildComponent(&testEntity); + + RakNet::BitStream bitStream; + quickBuildComponent.Serialize(bitStream, true); + + bitStream.ResetReadPointer(); + + // With destroyable component, should skip the special flags and go directly to ScriptedActivity + bool hasScriptedActivity; + ASSERT_TRUE(bitStream.Read(hasScriptedActivity)); + EXPECT_TRUE(hasScriptedActivity); + + uint32_t builderCount; + ASSERT_TRUE(bitStream.Read(builderCount)); + EXPECT_EQ(builderCount, 0); +} + +TEST_F(QuickBuildComponentTest, SerializeWithBuilder) { + Entity testEntity(15, info); + Entity builderEntity(20, info); + + QuickBuildComponent quickBuildComponent(&testEntity); + + // Simulate having a builder (this would normally be set through the component's logic) + // Since GetBuilder() is based on internal state, this test validates the serialization format + // when there's no builder + + RakNet::BitStream bitStream; + quickBuildComponent.Serialize(bitStream, true); + + bitStream.ResetReadPointer(); + + // Skip initial flags + bool flag1, flag2, flag3; + bitStream.Read(flag1); + bitStream.Read(flag2); + bitStream.Read(flag3); + + bool hasScriptedActivity; + ASSERT_TRUE(bitStream.Read(hasScriptedActivity)); + EXPECT_TRUE(hasScriptedActivity); + + uint32_t builderCount; + ASSERT_TRUE(bitStream.Read(builderCount)); + EXPECT_EQ(builderCount, 0); // No builder in default state +} + +TEST_F(QuickBuildComponentTest, SerializeConsistentFormat) { + Entity testEntity(15, info); + QuickBuildComponent quickBuildComponent(&testEntity); + + // Test that serialization format is consistent between calls + RakNet::BitStream firstStream, secondStream; + + quickBuildComponent.Serialize(firstStream, true); + quickBuildComponent.Serialize(secondStream, true); + + // Compare the serialized data + EXPECT_EQ(firstStream.GetNumberOfBitsUsed(), secondStream.GetNumberOfBitsUsed()); + + // Reset and compare bit by bit + firstStream.ResetReadPointer(); + secondStream.ResetReadPointer(); + + while (firstStream.GetNumberOfUnreadBits() > 0 && secondStream.GetNumberOfUnreadBits() > 0) { + bool firstBit, secondBit; + firstStream.Read(firstBit); + secondStream.Read(secondBit); + EXPECT_EQ(firstBit, secondBit); + } +} \ No newline at end of file diff --git a/tests/dGameTests/dComponentsTests/ScriptComponentTests.cpp b/tests/dGameTests/dComponentsTests/ScriptComponentTests.cpp new file mode 100644 index 00000000..9e7a649f --- /dev/null +++ b/tests/dGameTests/dComponentsTests/ScriptComponentTests.cpp @@ -0,0 +1,148 @@ +#include + +#include "ScriptComponent.h" +#include "Entity.h" +#include "BitStream.h" +#include "GameDependencies.h" + +class ScriptComponentTest : public GameDependenciesTest { +protected: + void SetUp() override { + SetUpDependencies(); + } + + void TearDown() override { + TearDownDependencies(); + } +}; + +TEST_F(ScriptComponentTest, SerializeInitialUpdateNoNetworkSettings) { + Entity testEntity(15, info); + ScriptComponent scriptComponent(&testEntity, "", false); + + RakNet::BitStream bitStream; + scriptComponent.Serialize(bitStream, true); + + // Read the data manually to validate serialization format + bitStream.ResetReadPointer(); + + bool hasNetworkSettings; + ASSERT_TRUE(bitStream.Read(hasNetworkSettings)); + EXPECT_FALSE(hasNetworkSettings); // No network settings by default +} + +TEST_F(ScriptComponentTest, SerializeRegularUpdate) { + Entity testEntity(15, info); + ScriptComponent scriptComponent(&testEntity, "", false); + + RakNet::BitStream bitStream; + scriptComponent.Serialize(bitStream, false); + + // Regular updates should not write anything for ScriptComponent + bitStream.ResetReadPointer(); + EXPECT_EQ(bitStream.GetNumberOfUnreadBits(), 0); +} + +TEST_F(ScriptComponentTest, SerializeWithNetworkSettings) { + Entity testEntity(15, info); + + // Add some network settings to the entity + testEntity.SetNetworkVar(u"test_float", 123.45f); + testEntity.SetNetworkVar(u"test_int", 42); + + ScriptComponent scriptComponent(&testEntity, "", false); + + RakNet::BitStream bitStream; + scriptComponent.Serialize(bitStream, true); + + bitStream.ResetReadPointer(); + + bool hasNetworkSettings; + ASSERT_TRUE(bitStream.Read(hasNetworkSettings)); + EXPECT_TRUE(hasNetworkSettings); // Should have network settings + + uint32_t ldfDataSize; + ASSERT_TRUE(bitStream.Read(ldfDataSize)); + EXPECT_GT(ldfDataSize, 0); // Should have some data + + // Verify the LDF data is present + RakNet::BitStream ldfStream; + ASSERT_TRUE(bitStream.Read(ldfStream, ldfDataSize)); + + ldfStream.ResetReadPointer(); + + uint8_t ldfType; + ASSERT_TRUE(ldfStream.Read(ldfType)); + EXPECT_EQ(ldfType, 0); // Always writes 0 first + + uint32_t settingsCount; + ASSERT_TRUE(ldfStream.Read(settingsCount)); + EXPECT_EQ(settingsCount, 2); // We added 2 settings +} + +TEST_F(ScriptComponentTest, SerializeConsistentBehavior) { + Entity testEntity(15, info); + ScriptComponent scriptComponent(&testEntity, "", false); + + // Test that multiple serializations are consistent + RakNet::BitStream firstStream, secondStream; + + scriptComponent.Serialize(firstStream, true); + scriptComponent.Serialize(secondStream, true); + + EXPECT_EQ(firstStream.GetNumberOfBitsUsed(), secondStream.GetNumberOfBitsUsed()); + + firstStream.ResetReadPointer(); + secondStream.ResetReadPointer(); + + bool firstHasSettings, secondHasSettings; + ASSERT_TRUE(firstStream.Read(firstHasSettings)); + ASSERT_TRUE(secondStream.Read(secondHasSettings)); + EXPECT_EQ(firstHasSettings, secondHasSettings); +} + +TEST_F(ScriptComponentTest, SerializeScriptNameHandling) { + Entity testEntity(15, info); + + // Test with different script names - serialization shouldn't change based on script name + ScriptComponent scriptComponent1(&testEntity, "TestScript", false); + ScriptComponent scriptComponent2(&testEntity, "AnotherScript", false); + + RakNet::BitStream stream1, stream2; + + scriptComponent1.Serialize(stream1, true); + scriptComponent2.Serialize(stream2, true); + + // Serialization should be the same regardless of script name since + // script names are not serialized, only network settings + stream1.ResetReadPointer(); + stream2.ResetReadPointer(); + + bool hasSettings1, hasSettings2; + ASSERT_TRUE(stream1.Read(hasSettings1)); + ASSERT_TRUE(stream2.Read(hasSettings2)); + EXPECT_EQ(hasSettings1, hasSettings2); + EXPECT_FALSE(hasSettings1); // Both should be false without network settings +} + +TEST_F(ScriptComponentTest, SerializeSerializedFlag) { + Entity testEntity(15, info); + ScriptComponent scriptComponent(&testEntity, "", false); + + // Test the serialized flag functionality + EXPECT_FALSE(scriptComponent.GetSerialized()); // Default state + + scriptComponent.SetSerialized(true); + EXPECT_TRUE(scriptComponent.GetSerialized()); + + // The serialized flag itself doesn't affect the Serialize method output, + // but it's tracked by the component + RakNet::BitStream bitStream; + scriptComponent.Serialize(bitStream, true); + + bitStream.ResetReadPointer(); + + bool hasNetworkSettings; + ASSERT_TRUE(bitStream.Read(hasNetworkSettings)); + EXPECT_FALSE(hasNetworkSettings); // Still no network settings +} \ No newline at end of file diff --git a/tests/dGameTests/dComponentsTests/SkillComponentTests.cpp b/tests/dGameTests/dComponentsTests/SkillComponentTests.cpp new file mode 100644 index 00000000..24b43933 --- /dev/null +++ b/tests/dGameTests/dComponentsTests/SkillComponentTests.cpp @@ -0,0 +1,102 @@ +#include + +#include "SkillComponent.h" +#include "Entity.h" +#include "BitStream.h" +#include "GameDependencies.h" + +class SkillComponentTest : public GameDependenciesTest { +protected: + void SetUp() override { + SetUpDependencies(); + } + + void TearDown() override { + TearDownDependencies(); + } +}; + +TEST_F(SkillComponentTest, SerializeInitialUpdate) { + Entity testEntity(15, info); + SkillComponent skillComponent(&testEntity); + + RakNet::BitStream bitStream; + skillComponent.Serialize(bitStream, true); + + // Read the data manually to validate serialization format + bitStream.ResetReadPointer(); + + bool skillFlag; + ASSERT_TRUE(bitStream.Read(skillFlag)); + EXPECT_FALSE(skillFlag); // Always writes 0 for initial update +} + +TEST_F(SkillComponentTest, SerializeRegularUpdate) { + Entity testEntity(15, info); + SkillComponent skillComponent(&testEntity); + + RakNet::BitStream bitStream; + skillComponent.Serialize(bitStream, false); + + // Regular updates should not write anything for SkillComponent + bitStream.ResetReadPointer(); + EXPECT_EQ(bitStream.GetNumberOfUnreadBits(), 0); +} + +TEST_F(SkillComponentTest, SerializeConsistentBehavior) { + Entity testEntity(15, info); + SkillComponent skillComponent(&testEntity); + + // Test that multiple initial serializations are consistent + RakNet::BitStream firstStream, secondStream; + + skillComponent.Serialize(firstStream, true); + skillComponent.Serialize(secondStream, true); + + EXPECT_EQ(firstStream.GetNumberOfBitsUsed(), secondStream.GetNumberOfBitsUsed()); + EXPECT_EQ(firstStream.GetNumberOfBitsUsed(), 1); // Should always be 1 bit (false) + + firstStream.ResetReadPointer(); + secondStream.ResetReadPointer(); + + bool firstFlag, secondFlag; + ASSERT_TRUE(firstStream.Read(firstFlag)); + ASSERT_TRUE(secondStream.Read(secondFlag)); + EXPECT_FALSE(firstFlag); + EXPECT_FALSE(secondFlag); + EXPECT_EQ(firstFlag, secondFlag); +} + +TEST_F(SkillComponentTest, GetUniqueSkillId) { + Entity testEntity(15, info); + SkillComponent skillComponent(&testEntity); + + // Test that unique skill IDs increment + uint32_t firstId = skillComponent.GetUniqueSkillId(); + uint32_t secondId = skillComponent.GetUniqueSkillId(); + uint32_t thirdId = skillComponent.GetUniqueSkillId(); + + EXPECT_EQ(secondId, firstId + 1); + EXPECT_EQ(thirdId, firstId + 2); + EXPECT_GT(firstId, 0); // Should start from at least 1 +} + +TEST_F(SkillComponentTest, SerializeAfterSkillUse) { + Entity testEntity(15, info); + SkillComponent skillComponent(&testEntity); + + // Generate some skill IDs to simulate skill usage + skillComponent.GetUniqueSkillId(); + skillComponent.GetUniqueSkillId(); + skillComponent.GetUniqueSkillId(); + + // Serialization behavior should still be the same + RakNet::BitStream bitStream; + skillComponent.Serialize(bitStream, true); + + bitStream.ResetReadPointer(); + + bool skillFlag; + ASSERT_TRUE(bitStream.Read(skillFlag)); + EXPECT_FALSE(skillFlag); // Still writes 0 regardless of internal state +} \ No newline at end of file diff --git a/tests/dGameTests/dComponentsTests/VendorComponentTests.cpp b/tests/dGameTests/dComponentsTests/VendorComponentTests.cpp new file mode 100644 index 00000000..5fe086e7 --- /dev/null +++ b/tests/dGameTests/dComponentsTests/VendorComponentTests.cpp @@ -0,0 +1,166 @@ +#include + +#include "VendorComponent.h" +#include "Entity.h" +#include "BitStream.h" +#include "GameDependencies.h" + +class VendorComponentTest : public GameDependenciesTest { +protected: + void SetUp() override { + SetUpDependencies(); + } + + void TearDown() override { + TearDownDependencies(); + } +}; + +TEST_F(VendorComponentTest, SerializeInitialUpdate) { + Entity testEntity(15, info); + VendorComponent vendorComponent(&testEntity); + + RakNet::BitStream bitStream; + vendorComponent.Serialize(bitStream, true); + + // Read the data manually to validate serialization format + bitStream.ResetReadPointer(); + + bool hasVendorInfo; + ASSERT_TRUE(bitStream.Read(hasVendorInfo)); + EXPECT_TRUE(hasVendorInfo); // Should always be true for initial update + + bool hasStandardCostItems; + ASSERT_TRUE(bitStream.Read(hasStandardCostItems)); + EXPECT_FALSE(hasStandardCostItems); // Default state after RefreshInventory + + bool hasMultiCostItems; + ASSERT_TRUE(bitStream.Read(hasMultiCostItems)); + EXPECT_FALSE(hasMultiCostItems); // Default state +} + +TEST_F(VendorComponentTest, SerializeRegularUpdate) { + Entity testEntity(15, info); + VendorComponent vendorComponent(&testEntity); + + // Reset dirty flag by doing initial serialization + RakNet::BitStream initStream; + vendorComponent.Serialize(initStream, true); + + // Test regular update with no changes + RakNet::BitStream bitStream; + vendorComponent.Serialize(bitStream, false); + + bitStream.ResetReadPointer(); + + bool hasVendorInfo; + ASSERT_TRUE(bitStream.Read(hasVendorInfo)); + EXPECT_FALSE(hasVendorInfo); // No dirty flags, so no data +} + +TEST_F(VendorComponentTest, SerializeWithDirtyVendor) { + Entity testEntity(15, info); + VendorComponent vendorComponent(&testEntity); + + // Reset dirty flag + RakNet::BitStream initStream; + vendorComponent.Serialize(initStream, true); + + // Make vendor dirty by changing state + vendorComponent.SetHasStandardCostItems(true); + + RakNet::BitStream bitStream; + vendorComponent.Serialize(bitStream, false); + + bitStream.ResetReadPointer(); + + bool hasVendorInfo; + ASSERT_TRUE(bitStream.Read(hasVendorInfo)); + EXPECT_TRUE(hasVendorInfo); // Should be true due to dirty flag + + bool hasStandardCostItems; + ASSERT_TRUE(bitStream.Read(hasStandardCostItems)); + EXPECT_TRUE(hasStandardCostItems); // Changed to true + + bool hasMultiCostItems; + ASSERT_TRUE(bitStream.Read(hasMultiCostItems)); + EXPECT_FALSE(hasMultiCostItems); // Still false +} + +TEST_F(VendorComponentTest, SerializeWithMultiCostItems) { + Entity testEntity(15, info); + VendorComponent vendorComponent(&testEntity); + + // Set both flags + vendorComponent.SetHasStandardCostItems(true); + vendorComponent.SetHasMultiCostItems(true); + + RakNet::BitStream bitStream; + vendorComponent.Serialize(bitStream, true); + + bitStream.ResetReadPointer(); + + bool hasVendorInfo; + ASSERT_TRUE(bitStream.Read(hasVendorInfo)); + EXPECT_TRUE(hasVendorInfo); + + bool hasStandardCostItems; + ASSERT_TRUE(bitStream.Read(hasStandardCostItems)); + EXPECT_TRUE(hasStandardCostItems); + + bool hasMultiCostItems; + ASSERT_TRUE(bitStream.Read(hasMultiCostItems)); + EXPECT_TRUE(hasMultiCostItems); +} + +TEST_F(VendorComponentTest, SerializeDirtyFlagClearing) { + Entity testEntity(15, info); + VendorComponent vendorComponent(&testEntity); + + // Make vendor dirty + vendorComponent.SetHasStandardCostItems(true); + + // First serialize should clear dirty flag + RakNet::BitStream firstStream; + vendorComponent.Serialize(firstStream, false); + + // Second serialize should show no vendor info + RakNet::BitStream secondStream; + vendorComponent.Serialize(secondStream, false); + + secondStream.ResetReadPointer(); + + bool hasVendorInfo; + ASSERT_TRUE(secondStream.Read(hasVendorInfo)); + EXPECT_FALSE(hasVendorInfo); // Dirty flag should be cleared +} + +TEST_F(VendorComponentTest, SettersChangeDirtyFlag) { + Entity testEntity(15, info); + VendorComponent vendorComponent(&testEntity); + + // Clear initial dirty state + RakNet::BitStream initStream; + vendorComponent.Serialize(initStream, true); + + // Setting same value should not make dirty + vendorComponent.SetHasStandardCostItems(false); // Already false + + RakNet::BitStream noChangeStream; + vendorComponent.Serialize(noChangeStream, false); + noChangeStream.ResetReadPointer(); + + bool hasVendorInfo; + ASSERT_TRUE(noChangeStream.Read(hasVendorInfo)); + EXPECT_FALSE(hasVendorInfo); // Should not be dirty + + // Setting different value should make dirty + vendorComponent.SetHasStandardCostItems(true); + + RakNet::BitStream changeStream; + vendorComponent.Serialize(changeStream, false); + changeStream.ResetReadPointer(); + + ASSERT_TRUE(changeStream.Read(hasVendorInfo)); + EXPECT_TRUE(hasVendorInfo); // Should be dirty now +} \ No newline at end of file