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"
"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

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->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();
}