diff --git a/tests/dGameTests/dComponentsTests/CMakeLists.txt b/tests/dGameTests/dComponentsTests/CMakeLists.txt index 1d3cdb5e..8499d4df 100644 --- a/tests/dGameTests/dComponentsTests/CMakeLists.txt +++ b/tests/dGameTests/dComponentsTests/CMakeLists.txt @@ -2,15 +2,23 @@ set(DCOMPONENTS_TESTS "ActivityComponentTests.cpp" "BaseCombatAIComponentTests.cpp" "BouncerComponentTests.cpp" + "BuffComponentTests.cpp" "CollectibleComponentTests.cpp" + "ControllablePhysicsComponentTests.cpp" "DestroyableComponentTests.cpp" + "DonationVendorComponentTests.cpp" "HavokVehiclePhysicsComponentTests.cpp" + "ItemComponentTests.cpp" + "LevelProgressionComponentTests.cpp" "LUPExhibitComponentTests.cpp" + "MiniGameControlComponentTests.cpp" "ModelComponentTests.cpp" "MovingPlatformComponentTests.cpp" "PetComponentTests.cpp" - "SimplePhysicsComponentTests.cpp" + "RenderComponentTests.cpp" "SavingTests.cpp" + "SimplePhysicsComponentTests.cpp" + "SwitchComponentTests.cpp" ) # Get the folder name and prepend it to the files above diff --git a/tests/dGameTests/dComponentsTests/DonationVendorComponentTests.cpp b/tests/dGameTests/dComponentsTests/DonationVendorComponentTests.cpp new file mode 100644 index 00000000..8217a7fc --- /dev/null +++ b/tests/dGameTests/dComponentsTests/DonationVendorComponentTests.cpp @@ -0,0 +1,169 @@ +#include "GameDependencies.h" +#include + +#include "BitStream.h" +#include "DonationVendorComponent.h" +#include "Entity.h" +#include "eReplicaComponentType.h" + +class DonationVendorComponentTest : public GameDependenciesTest { +protected: + Entity* baseEntity; + DonationVendorComponent* donationVendorComponent; + CBITSTREAM + uint32_t flags = 0; + + void SetUp() override { + SetUpDependencies(); + baseEntity = new Entity(15, GameDependenciesTest::info); + // Set a custom goal for testing + baseEntity->SetVar(u"donationGoal", 1000); + baseEntity->SetVar(u"activityID", 123); + donationVendorComponent = baseEntity->AddComponent(); + } + + void TearDown() override { + delete baseEntity; + TearDownDependencies(); + } +}; + +// Test initial serialization with no donations +TEST_F(DonationVendorComponentTest, InitialSerialization) { + donationVendorComponent->Serialize(bitStream, true); + + // Read VendorComponent serialization first + bool vendorDirtyFlag; + bitStream.Read(vendorDirtyFlag); + EXPECT_TRUE(vendorDirtyFlag); // Should be true for initial update + + if (vendorDirtyFlag) { + bool hasStandardCostItems; + bool hasMultiCostItems; + bitStream.Read(hasStandardCostItems); + bitStream.Read(hasMultiCostItems); + EXPECT_FALSE(hasStandardCostItems); + EXPECT_FALSE(hasMultiCostItems); + } + + // Read DonationVendorComponent serialization + bool donationDirtyFlag; + bitStream.Read(donationDirtyFlag); + EXPECT_TRUE(donationDirtyFlag); // Should be true for initial update + + if (donationDirtyFlag) { + float percentComplete; + int32_t totalDonated; + int32_t totalRemaining; + + bitStream.Read(percentComplete); + bitStream.Read(totalDonated); + bitStream.Read(totalRemaining); + + EXPECT_EQ(percentComplete, 0.0f); + EXPECT_EQ(totalDonated, 0); + EXPECT_EQ(totalRemaining, 1000); + } + + bitStream.Reset(); +} + +// Test serialization after donations +TEST_F(DonationVendorComponentTest, SerializationAfterDonations) { + // Submit some donations + donationVendorComponent->SubmitDonation(250); + + donationVendorComponent->Serialize(bitStream, false); + + // Read VendorComponent serialization first + bool vendorDirtyFlag; + bitStream.Read(vendorDirtyFlag); + EXPECT_FALSE(vendorDirtyFlag); // Should be false for regular update + + // Read DonationVendorComponent serialization + bool donationDirtyFlag; + bitStream.Read(donationDirtyFlag); + EXPECT_TRUE(donationDirtyFlag); // Should be true because we submitted donations + + if (donationDirtyFlag) { + float percentComplete; + int32_t totalDonated; + int32_t totalRemaining; + + bitStream.Read(percentComplete); + bitStream.Read(totalDonated); + bitStream.Read(totalRemaining); + + EXPECT_EQ(percentComplete, 0.25f); // 250/1000 = 0.25 + EXPECT_EQ(totalDonated, 250); + EXPECT_EQ(totalRemaining, 750); + } + + bitStream.Reset(); +} + +// Test default jawbox activity (ID 117) +TEST_F(DonationVendorComponentTest, JawboxActivitySerialization) { + delete baseEntity; + baseEntity = new Entity(15, GameDependenciesTest::info); + baseEntity->SetVar(u"activityID", 117); // Jawbox activity + donationVendorComponent = baseEntity->AddComponent(); + + donationVendorComponent->Serialize(bitStream, true); + + // Read VendorComponent serialization first + bool vendorDirtyFlag; + bitStream.Read(vendorDirtyFlag); + EXPECT_TRUE(vendorDirtyFlag); + + if (vendorDirtyFlag) { + bool hasStandardCostItems; + bool hasMultiCostItems; + bitStream.Read(hasStandardCostItems); + bitStream.Read(hasMultiCostItems); + } + + // Read DonationVendorComponent serialization + bool donationDirtyFlag; + bitStream.Read(donationDirtyFlag); + EXPECT_TRUE(donationDirtyFlag); + + if (donationDirtyFlag) { + float percentComplete; + int32_t totalDonated; + int32_t totalRemaining; + + bitStream.Read(percentComplete); + bitStream.Read(totalDonated); + bitStream.Read(totalRemaining); + + // Jawbox activity should show as complete + EXPECT_EQ(percentComplete, 1.0f); + EXPECT_EQ(totalDonated, INT32_MAX); + EXPECT_EQ(totalRemaining, 0); + } + + bitStream.Reset(); +} + +// Test regular update without changes (dirty flag should be false) +TEST_F(DonationVendorComponentTest, RegularUpdateWithoutChanges) { + // First do an initial update to clear the dirty flag + donationVendorComponent->Serialize(bitStream, true); + bitStream.Reset(); + + // Now do a regular update without any changes + donationVendorComponent->Serialize(bitStream, false); + + // Read VendorComponent serialization first + bool vendorDirtyFlag; + bitStream.Read(vendorDirtyFlag); + EXPECT_FALSE(vendorDirtyFlag); + + // Read DonationVendorComponent serialization + bool donationDirtyFlag; + bitStream.Read(donationDirtyFlag); + EXPECT_FALSE(donationDirtyFlag); // Should be false since nothing changed + + bitStream.Reset(); +} \ No newline at end of file diff --git a/tests/dGameTests/dComponentsTests/ItemComponentTests.cpp b/tests/dGameTests/dComponentsTests/ItemComponentTests.cpp new file mode 100644 index 00000000..31a7eab9 --- /dev/null +++ b/tests/dGameTests/dComponentsTests/ItemComponentTests.cpp @@ -0,0 +1,83 @@ +#include "GameDependencies.h" +#include + +#include "BitStream.h" +#include "ItemComponent.h" +#include "Entity.h" +#include "eReplicaComponentType.h" + +class ItemComponentTest : public GameDependenciesTest { +protected: + Entity* baseEntity; + ItemComponent* itemComponent; + CBITSTREAM + uint32_t flags = 0; + + void SetUp() override { + SetUpDependencies(); + baseEntity = new Entity(15, GameDependenciesTest::info); + itemComponent = baseEntity->AddComponent(); + } + + void TearDown() override { + delete baseEntity; + TearDownDependencies(); + } +}; + +// Test serialization behavior (should just write a single 0 bit) +TEST_F(ItemComponentTest, SerializationBehavior) { + itemComponent->Serialize(bitStream, true); + + // ItemComponent::Serialize just writes a single 0 bit + ASSERT_EQ(bitStream.GetNumberOfUnreadBits(), 1); + + bool value; + bitStream.Read(value); + EXPECT_FALSE(value); // Should be false (0 bit) + + bitStream.Reset(); +} + +// Test serialization with isConstruction = false +TEST_F(ItemComponentTest, SerializationWithoutConstruction) { + itemComponent->Serialize(bitStream, false); + + // Should still just write a single 0 bit regardless of isConstruction parameter + ASSERT_EQ(bitStream.GetNumberOfUnreadBits(), 1); + + bool value; + bitStream.Read(value); + EXPECT_FALSE(value); // Should be false (0 bit) + + bitStream.Reset(); +} + +// Test multiple serializations produce consistent results +TEST_F(ItemComponentTest, ConsistentSerialization) { + // First serialization + itemComponent->Serialize(bitStream, true); + ASSERT_EQ(bitStream.GetNumberOfUnreadBits(), 1); + bool value1; + bitStream.Read(value1); + bitStream.Reset(); + + // Second serialization + itemComponent->Serialize(bitStream, false); + ASSERT_EQ(bitStream.GetNumberOfUnreadBits(), 1); + bool value2; + bitStream.Read(value2); + bitStream.Reset(); + + // Third serialization + itemComponent->Serialize(bitStream, true); + ASSERT_EQ(bitStream.GetNumberOfUnreadBits(), 1); + bool value3; + bitStream.Read(value3); + + EXPECT_EQ(value1, value2); + EXPECT_EQ(value2, value3); + EXPECT_FALSE(value1); // All should be false + + bitStream.Reset(); +} \ No newline at end of file diff --git a/tests/dGameTests/dComponentsTests/LevelProgressionComponentTests.cpp b/tests/dGameTests/dComponentsTests/LevelProgressionComponentTests.cpp new file mode 100644 index 00000000..0bf695e3 --- /dev/null +++ b/tests/dGameTests/dComponentsTests/LevelProgressionComponentTests.cpp @@ -0,0 +1,97 @@ +#include "GameDependencies.h" +#include + +#include "BitStream.h" +#include "LevelProgressionComponent.h" +#include "Entity.h" +#include "eReplicaComponentType.h" + +class LevelProgressionComponentTest : public GameDependenciesTest { +protected: + Entity* baseEntity; + LevelProgressionComponent* levelProgressionComponent; + CBITSTREAM + uint32_t flags = 0; + + void SetUp() override { + SetUpDependencies(); + baseEntity = new Entity(15, GameDependenciesTest::info); + levelProgressionComponent = baseEntity->AddComponent(); + } + + void TearDown() override { + delete baseEntity; + TearDownDependencies(); + } +}; + +// Test initial serialization +TEST_F(LevelProgressionComponentTest, InitialSerialization) { + levelProgressionComponent->Serialize(bitStream, true); + + // Should write dirty flag and level + bool dirtyFlag; + uint32_t level; + + bitStream.Read(dirtyFlag); + EXPECT_TRUE(dirtyFlag); // Should be true for initial update + + bitStream.Read(level); + EXPECT_EQ(level, 1); // Default level should be 1 + + bitStream.Reset(); +} + +// Test regular update without level change +TEST_F(LevelProgressionComponentTest, RegularUpdateWithoutChange) { + // First do initial serialization to clear dirty flag + levelProgressionComponent->Serialize(bitStream, true); + bitStream.Reset(); + + // Now do regular update + levelProgressionComponent->Serialize(bitStream, false); + + bool dirtyFlag; + bitStream.Read(dirtyFlag); + EXPECT_FALSE(dirtyFlag); // Should be false since level didn't change + + bitStream.Reset(); +} + +// Test serialization after level change +TEST_F(LevelProgressionComponentTest, SerializationAfterLevelChange) { + // Set a different level + levelProgressionComponent->SetLevel(5); + + levelProgressionComponent->Serialize(bitStream, false); + + bool dirtyFlag; + uint32_t level; + + bitStream.Read(dirtyFlag); + EXPECT_TRUE(dirtyFlag); // Should be true since level changed + + bitStream.Read(level); + EXPECT_EQ(level, 5); + + bitStream.Reset(); +} + +// Test that dirty flag gets cleared after serialization +TEST_F(LevelProgressionComponentTest, DirtyFlagClearedAfterSerialization) { + // Change level to make it dirty + levelProgressionComponent->SetLevel(3); + + // First serialization + levelProgressionComponent->Serialize(bitStream, false); + bitStream.Reset(); + + // Second serialization should not be dirty + levelProgressionComponent->Serialize(bitStream, false); + + bool dirtyFlag; + bitStream.Read(dirtyFlag); + EXPECT_FALSE(dirtyFlag); // Should be false since dirty flag was cleared + + bitStream.Reset(); +} \ No newline at end of file diff --git a/tests/dGameTests/dComponentsTests/MiniGameControlComponentTests.cpp b/tests/dGameTests/dComponentsTests/MiniGameControlComponentTests.cpp new file mode 100644 index 00000000..c6266cb0 --- /dev/null +++ b/tests/dGameTests/dComponentsTests/MiniGameControlComponentTests.cpp @@ -0,0 +1,83 @@ +#include "GameDependencies.h" +#include + +#include "BitStream.h" +#include "MiniGameControlComponent.h" +#include "Entity.h" +#include "eReplicaComponentType.h" + +class MiniGameControlComponentTest : public GameDependenciesTest { +protected: + Entity* baseEntity; + MiniGameControlComponent* miniGameControlComponent; + CBITSTREAM + uint32_t flags = 0; + + void SetUp() override { + SetUpDependencies(); + baseEntity = new Entity(15, GameDependenciesTest::info); + miniGameControlComponent = baseEntity->AddComponent(); + } + + void TearDown() override { + delete baseEntity; + TearDownDependencies(); + } +}; + +// Test serialization behavior (should always write 0x40000000) +TEST_F(MiniGameControlComponentTest, SerializationBehavior) { + miniGameControlComponent->Serialize(bitStream, true); + + // MiniGameControlComponent::Serialize writes a fixed uint32_t value + ASSERT_EQ(bitStream.GetNumberOfUnreadBits(), 32); + + uint32_t value; + bitStream.Read(value); + EXPECT_EQ(value, 0x40000000); + + bitStream.Reset(); +} + +// Test serialization with isConstruction = false +TEST_F(MiniGameControlComponentTest, SerializationWithoutConstruction) { + miniGameControlComponent->Serialize(bitStream, false); + + // Should write the same value regardless of isConstruction parameter + ASSERT_EQ(bitStream.GetNumberOfUnreadBits(), 32); + + uint32_t value; + bitStream.Read(value); + EXPECT_EQ(value, 0x40000000); + + bitStream.Reset(); +} + +// Test multiple serializations produce consistent results +TEST_F(MiniGameControlComponentTest, ConsistentSerialization) { + // First serialization + miniGameControlComponent->Serialize(bitStream, true); + ASSERT_EQ(bitStream.GetNumberOfUnreadBits(), 32); + uint32_t value1; + bitStream.Read(value1); + bitStream.Reset(); + + // Second serialization + miniGameControlComponent->Serialize(bitStream, false); + ASSERT_EQ(bitStream.GetNumberOfUnreadBits(), 32); + uint32_t value2; + bitStream.Read(value2); + bitStream.Reset(); + + // Third serialization + miniGameControlComponent->Serialize(bitStream, true); + ASSERT_EQ(bitStream.GetNumberOfUnreadBits(), 32); + uint32_t value3; + bitStream.Read(value3); + + EXPECT_EQ(value1, value2); + EXPECT_EQ(value2, value3); + EXPECT_EQ(value1, 0x40000000); // All should be 0x40000000 + + bitStream.Reset(); +} \ No newline at end of file diff --git a/tests/dGameTests/dComponentsTests/PetComponentTests.cpp b/tests/dGameTests/dComponentsTests/PetComponentTests.cpp index 75ce4ec8..8cde94ef 100644 --- a/tests/dGameTests/dComponentsTests/PetComponentTests.cpp +++ b/tests/dGameTests/dComponentsTests/PetComponentTests.cpp @@ -41,3 +41,184 @@ TEST_F(PetTest, PlacementNewAddComponentTest) { ASSERT_EQ(petComponent->GetParent()->GetObjectID(), 15); ASSERT_EQ(petComponent->GetAbility(), ePetAbilityType::Invalid); } + +// Test untamed pet serialization (initial update) +TEST_F(PetTest, UntamedPetInitialSerialization) { + petComponent->Serialize(bitStream, true); + + // Read the serialized data manually + bool alwaysDirty; + uint32_t status; + ePetAbilityType ability; + bool interacting; + bool tamed; + bool tamedForInitial; + + bitStream.Read(alwaysDirty); + EXPECT_TRUE(alwaysDirty); // Always true + + bitStream.Read(status); + EXPECT_EQ(status, 0); // Default status should be 0 + + bitStream.Read(ability); + EXPECT_EQ(ability, ePetAbilityType::Invalid); // Should be Invalid for untamed pets + + bitStream.Read(interacting); + EXPECT_FALSE(interacting); // No interaction by default + + bitStream.Read(tamed); + EXPECT_FALSE(tamed); // Pet is not tamed by default + + // For initial update, should write tamed flag again + bitStream.Read(tamedForInitial); + EXPECT_FALSE(tamedForInitial); // Should match tamed flag + + bitStream.Reset(); +} + +// Test tamed pet serialization (initial update) +TEST_F(PetTest, TamedPetInitialSerialization) { + // Set up a tamed pet + LWOOBJID ownerID = 12345; + petComponent->Activate(ownerID, false, false); + petComponent->SetPetNameForModeration("TestPet"); + petComponent->SetOwnerName("TestOwner"); + + petComponent->Serialize(bitStream, true); + + // Read the serialized data manually + bool alwaysDirty; + uint32_t status; + ePetAbilityType ability; + bool interacting; + bool tamed; + LWOOBJID owner; + bool tamedForInitial; + uint32_t moderationStatus; + uint8_t nameLength; + std::vector nameData; + uint8_t ownerNameLength; + std::vector ownerNameData; + + bitStream.Read(alwaysDirty); + EXPECT_TRUE(alwaysDirty); // Always true + + bitStream.Read(status); + bitStream.Read(ability); + EXPECT_NE(ability, ePetAbilityType::Invalid); // Should have a valid ability when tamed + + bitStream.Read(interacting); + EXPECT_FALSE(interacting); // No interaction by default + + bitStream.Read(tamed); + EXPECT_TRUE(tamed); // Pet should be tamed + + if (tamed) { + bitStream.Read(owner); + EXPECT_EQ(owner, ownerID); + } + + // For initial update with tamed pet + bitStream.Read(tamedForInitial); + EXPECT_TRUE(tamedForInitial); + + if (tamedForInitial) { + bitStream.Read(moderationStatus); + EXPECT_EQ(moderationStatus, 0); // Default moderation status + + bitStream.Read(nameLength); + EXPECT_GT(nameLength, 0); // Should have a name + + nameData.resize(nameLength); + for (uint8_t i = 0; i < nameLength; i++) { + bitStream.Read(nameData[i]); + } + + bitStream.Read(ownerNameLength); + EXPECT_GT(ownerNameLength, 0); // Should have an owner name + + ownerNameData.resize(ownerNameLength); + for (uint8_t i = 0; i < ownerNameLength; i++) { + bitStream.Read(ownerNameData[i]); + } + } + + bitStream.Reset(); +} + +// Test tamed pet regular update serialization +TEST_F(PetTest, TamedPetRegularSerialization) { + // Set up a tamed pet + LWOOBJID ownerID = 12345; + petComponent->Activate(ownerID, false, false); + + petComponent->Serialize(bitStream, false); + + // Read the serialized data manually + bool alwaysDirty; + uint32_t status; + ePetAbilityType ability; + bool interacting; + bool tamed; + LWOOBJID owner; + + bitStream.Read(alwaysDirty); + EXPECT_TRUE(alwaysDirty); // Always true + + bitStream.Read(status); + bitStream.Read(ability); + EXPECT_NE(ability, ePetAbilityType::Invalid); // Should have a valid ability when tamed + + bitStream.Read(interacting); + EXPECT_FALSE(interacting); // No interaction by default + + bitStream.Read(tamed); + EXPECT_TRUE(tamed); // Pet should be tamed + + if (tamed) { + bitStream.Read(owner); + EXPECT_EQ(owner, ownerID); + } + + // Regular update should not include initial update data + EXPECT_EQ(bitStream.GetNumberOfUnreadBits(), 0); + + bitStream.Reset(); +} + +// Test pet with interaction serialization +TEST_F(PetTest, PetWithInteractionSerialization) { + // Set up a pet with interaction + LWOOBJID interactionID = 67890; + petComponent->SetInteraction(interactionID); + + petComponent->Serialize(bitStream, false); + + // Read the serialized data manually + bool alwaysDirty; + uint32_t status; + ePetAbilityType ability; + bool interacting; + LWOOBJID interaction; + bool tamed; + + bitStream.Read(alwaysDirty); + EXPECT_TRUE(alwaysDirty); // Always true + + bitStream.Read(status); + bitStream.Read(ability); + EXPECT_EQ(ability, ePetAbilityType::Invalid); // Should be Invalid for untamed pets + + bitStream.Read(interacting); + EXPECT_TRUE(interacting); // Should be true + + if (interacting) { + bitStream.Read(interaction); + EXPECT_EQ(interaction, interactionID); + } + + bitStream.Read(tamed); + EXPECT_FALSE(tamed); // Pet is not tamed by default + + bitStream.Reset(); +}