Add DonationVendorComponent, ItemComponent, LevelProgressionComponent, MiniGameControlComponent tests and enhance PetComponent tests

Co-authored-by: aronwk-aaron <26027722+aronwk-aaron@users.noreply.github.com>
This commit is contained in:
copilot-swe-agent[bot]
2025-08-31 22:37:18 +00:00
parent c29f0d151e
commit f4a9cd21be
6 changed files with 622 additions and 1 deletions

View File

@@ -2,15 +2,23 @@ set(DCOMPONENTS_TESTS
"ActivityComponentTests.cpp" "ActivityComponentTests.cpp"
"BaseCombatAIComponentTests.cpp" "BaseCombatAIComponentTests.cpp"
"BouncerComponentTests.cpp" "BouncerComponentTests.cpp"
"BuffComponentTests.cpp"
"CollectibleComponentTests.cpp" "CollectibleComponentTests.cpp"
"ControllablePhysicsComponentTests.cpp"
"DestroyableComponentTests.cpp" "DestroyableComponentTests.cpp"
"DonationVendorComponentTests.cpp"
"HavokVehiclePhysicsComponentTests.cpp" "HavokVehiclePhysicsComponentTests.cpp"
"ItemComponentTests.cpp"
"LevelProgressionComponentTests.cpp"
"LUPExhibitComponentTests.cpp" "LUPExhibitComponentTests.cpp"
"MiniGameControlComponentTests.cpp"
"ModelComponentTests.cpp" "ModelComponentTests.cpp"
"MovingPlatformComponentTests.cpp" "MovingPlatformComponentTests.cpp"
"PetComponentTests.cpp" "PetComponentTests.cpp"
"SimplePhysicsComponentTests.cpp" "RenderComponentTests.cpp"
"SavingTests.cpp" "SavingTests.cpp"
"SimplePhysicsComponentTests.cpp"
"SwitchComponentTests.cpp"
) )
# Get the folder name and prepend it to the files above # Get the folder name and prepend it to the files above

View File

@@ -0,0 +1,169 @@
#include "GameDependencies.h"
#include <gtest/gtest.h>
#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<int32_t>(u"donationGoal", 1000);
baseEntity->SetVar<uint32_t>(u"activityID", 123);
donationVendorComponent = baseEntity->AddComponent<DonationVendorComponent>();
}
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<uint32_t>(u"activityID", 117); // Jawbox activity
donationVendorComponent = baseEntity->AddComponent<DonationVendorComponent>();
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();
}

View File

@@ -0,0 +1,83 @@
#include "GameDependencies.h"
#include <gtest/gtest.h>
#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<ItemComponent>();
}
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();
}

View File

@@ -0,0 +1,97 @@
#include "GameDependencies.h"
#include <gtest/gtest.h>
#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<LevelProgressionComponent>();
}
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();
}

View File

@@ -0,0 +1,83 @@
#include "GameDependencies.h"
#include <gtest/gtest.h>
#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<MiniGameControlComponent>();
}
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();
}

View File

@@ -41,3 +41,184 @@ TEST_F(PetTest, PlacementNewAddComponentTest) {
ASSERT_EQ(petComponent->GetParent()->GetObjectID(), 15); ASSERT_EQ(petComponent->GetParent()->GetObjectID(), 15);
ASSERT_EQ(petComponent->GetAbility(), ePetAbilityType::Invalid); 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<uint16_t> nameData;
uint8_t ownerNameLength;
std::vector<uint16_t> 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();
}