Improve CharacterComponent tests to follow proper variable testing pattern and address feedback on testing each component variable

Co-authored-by: aronwk-aaron <26027722+aronwk-aaron@users.noreply.github.com>
This commit is contained in:
copilot-swe-agent[bot]
2025-08-31 06:53:34 +00:00
parent 3c111735bc
commit 2b0791130f

View File

@@ -7,22 +7,22 @@
#include "Character.h" #include "Character.h"
#include "User.h" #include "User.h"
#include "eReplicaComponentType.h" #include "eReplicaComponentType.h"
#include "eStateChangeType.h" #include "eGameActivity.h"
class CharacterComponentTest : public GameDependenciesTest { class CharacterComponentTest : public GameDependenciesTest {
protected: protected:
std::unique_ptr<Entity> baseEntity; Entity* baseEntity;
CharacterComponent* characterComponent; CharacterComponent* characterComponent;
std::unique_ptr<Character> character; std::unique_ptr<Character> character;
std::unique_ptr<User> user; std::unique_ptr<User> user;
CBITSTREAM; CBITSTREAM
uint32_t flags = 0;
void SetUp() override { void SetUp() override {
SetUpDependencies(); SetUpDependencies();
// Create a mock user and character // Create a mock user and character
user = std::make_unique<User>(UNASSIGNED_SYSTEM_ADDRESS, "", "TestUser"); user = std::make_unique<User>(UNASSIGNED_SYSTEM_ADDRESS, "", "TestUser");
// Note: User account ID is set internally
character = std::make_unique<Character>(1, user.get()); character = std::make_unique<Character>(1, user.get());
character->SetHairColor(5); character->SetHairColor(5);
@@ -33,161 +33,218 @@ protected:
character->SetEyebrows(3); character->SetEyebrows(3);
character->SetEyes(7); character->SetEyes(7);
character->SetMouth(9); character->SetMouth(9);
// Note: Last login is set internally
baseEntity = std::make_unique<Entity>(15, GameDependenciesTest::info); baseEntity = new Entity(15, GameDependenciesTest::info);
characterComponent = baseEntity->AddComponent<CharacterComponent>(character.get(), UNASSIGNED_SYSTEM_ADDRESS); characterComponent = baseEntity->AddComponent<CharacterComponent>(character.get(), UNASSIGNED_SYSTEM_ADDRESS);
// Note: Statistics are set internally through game actions, not directly settable // Set some test values using available setter methods
characterComponent->SetUScore(12345);
characterComponent->SetCurrentActivity(eGameActivity::QUICKBUILDING);
characterComponent->SetReputation(6789);
characterComponent->SetPvpEnabled(true);
characterComponent->SetLastRocketConfig(u"test,rocket,config");
// Update some statistics using the UpdatePlayerStatistic method
characterComponent->UpdatePlayerStatistic(StatisticID::CurrencyCollected, 100);
characterComponent->UpdatePlayerStatistic(StatisticID::BricksCollected, 200);
characterComponent->UpdatePlayerStatistic(StatisticID::SmashablesSmashed, 50);
characterComponent->UpdatePlayerStatistic(StatisticID::QuickBuildsCompleted, 25);
characterComponent->UpdatePlayerStatistic(StatisticID::EnemiesSmashed, 75);
} }
void TearDown() override { void TearDown() override {
delete baseEntity;
TearDownDependencies(); TearDownDependencies();
} }
}; };
/**
* Test Construction of a CharacterComponent
*/
TEST_F(CharacterComponentTest, CharacterComponentSerializeConstructionTest) { TEST_F(CharacterComponentTest, CharacterComponentSerializeConstructionTest) {
characterComponent->Serialize(bitStream, true); characterComponent->Serialize(bitStream, true);
// Read back the serialized data to verify structure {
bool hasClaimCode0; // Read back the serialized data to verify structure
bitStream.Read(hasClaimCode0); bool hasClaimCode0, hasClaimCode1, hasClaimCode2, hasClaimCode3;
ASSERT_FALSE(hasClaimCode0); // Default is 0 bitStream.Read(hasClaimCode0);
bitStream.Read(hasClaimCode1);
bitStream.Read(hasClaimCode2);
bitStream.Read(hasClaimCode3);
bool hasClaimCode1; EXPECT_FALSE(hasClaimCode0); // Default is 0
bitStream.Read(hasClaimCode1); EXPECT_FALSE(hasClaimCode1); // Default is 0
ASSERT_FALSE(hasClaimCode1); // Default is 0 EXPECT_FALSE(hasClaimCode2); // Default is 0
EXPECT_FALSE(hasClaimCode3); // Default is 0
bool hasClaimCode2; // Character appearance data
bitStream.Read(hasClaimCode2); uint32_t hairColor, hairStyle, head, shirtColor, pantsColor, shirtStyle, headColor;
ASSERT_FALSE(hasClaimCode2); // Default is 0 uint32_t eyebrows, eyes, mouth;
uint64_t accountId, lastLogin, propModLastDisplayTime, uScore;
bool freeToPlay;
bool hasClaimCode3; bitStream.Read(hairColor);
bitStream.Read(hasClaimCode3); bitStream.Read(hairStyle);
ASSERT_FALSE(hasClaimCode3); // Default is 0 bitStream.Read(head);
bitStream.Read(shirtColor);
bitStream.Read(pantsColor);
bitStream.Read(shirtStyle);
bitStream.Read(headColor);
bitStream.Read(eyebrows);
bitStream.Read(eyes);
bitStream.Read(mouth);
bitStream.Read(accountId);
bitStream.Read(lastLogin);
bitStream.Read(propModLastDisplayTime);
bitStream.Read(uScore);
bitStream.Read(freeToPlay);
// Character appearance data // Verify character appearance values
uint32_t hairColor, hairStyle, head, shirtColor, pantsColor, shirtStyle, headColor; EXPECT_EQ(hairColor, 5);
uint32_t eyebrows, eyes, mouth; EXPECT_EQ(hairStyle, 10);
uint64_t accountId, lastLogin, propModLastDisplayTime, uScore; EXPECT_EQ(head, 0); // Default value
bool freeToPlay; EXPECT_EQ(shirtColor, 15);
EXPECT_EQ(pantsColor, 20);
EXPECT_EQ(shirtStyle, 25);
EXPECT_EQ(headColor, 0); // Default value
EXPECT_EQ(eyebrows, 3);
EXPECT_EQ(eyes, 7);
EXPECT_EQ(mouth, 9);
bitStream.Read(hairColor); // Account and score values
bitStream.Read(hairStyle); EXPECT_GE(accountId, 0); // Valid account ID
bitStream.Read(head); EXPECT_GE(lastLogin, 0); // Valid last login
bitStream.Read(shirtColor); EXPECT_EQ(propModLastDisplayTime, 0); // Default value
bitStream.Read(pantsColor); EXPECT_EQ(uScore, 12345); // Value we set
bitStream.Read(shirtStyle); EXPECT_FALSE(freeToPlay); // Default value
bitStream.Read(headColor);
bitStream.Read(eyebrows);
bitStream.Read(eyes);
bitStream.Read(mouth);
bitStream.Read(accountId);
bitStream.Read(lastLogin);
bitStream.Read(propModLastDisplayTime);
bitStream.Read(uScore);
bitStream.Read(freeToPlay);
ASSERT_EQ(hairColor, 5); // Statistics verification - read all statistics values
ASSERT_EQ(hairStyle, 10); uint64_t currencyCollected, bricksCollected, smashablesSmashed, quickBuildsCompleted;
ASSERT_EQ(head, 0); uint64_t enemiesSmashed, rocketsUsed, missionsCompleted, petsTamed;
ASSERT_EQ(shirtColor, 15); uint64_t imaginationPowerUps, lifePowerUps, armorPowerUps, metersTraveled;
ASSERT_EQ(pantsColor, 20); uint64_t timesSmashed, totalDamageTaken, totalDamageHealed, totalArmorRepaired;
ASSERT_EQ(shirtStyle, 25); uint64_t totalImaginationRestored, totalImaginationUsed, distanceDriven, timeAirborneInCar;
ASSERT_EQ(headColor, 0); uint64_t racingImaginationPowerUps, racingImaginationCrates, racingCarBoosts;
ASSERT_EQ(eyebrows, 3); uint64_t racingTimesWrecked, racingSmashablesSmashed, racesFinished, firstPlaceRaces;
ASSERT_EQ(eyes, 7);
ASSERT_EQ(mouth, 9);
// Account ID and other values are set internally
ASSERT_GE(accountId, 0); // Just verify it's a valid number
ASSERT_GE(lastLogin, 0);
ASSERT_EQ(propModLastDisplayTime, 0);
ASSERT_GE(uScore, 0); // U-score starts at 0
ASSERT_FALSE(freeToPlay);
// Statistics verification bitStream.Read(currencyCollected);
uint64_t currencyCollected, bricksCollected, smashablesSmashed, quickBuildsCompleted; bitStream.Read(bricksCollected);
uint64_t enemiesSmashed, rocketsUsed, missionsCompleted, petsTamed; bitStream.Read(smashablesSmashed);
uint64_t imaginationPowerUps, lifePowerUps, armorPowerUps, metersTraveled; bitStream.Read(quickBuildsCompleted);
uint64_t timesSmashed, totalDamageTaken, totalDamageHealed, totalArmorRepaired; bitStream.Read(enemiesSmashed);
uint64_t totalImaginationRestored, totalImaginationUsed, distanceDriven, timeAirborneInCar; bitStream.Read(rocketsUsed);
uint64_t racingImaginationPowerUps, racingImaginationCrates, racingCarBoosts; bitStream.Read(missionsCompleted);
uint64_t racingTimesWrecked, racingSmashablesSmashed, racesFinished, firstPlaceRaces; bitStream.Read(petsTamed);
bitStream.Read(imaginationPowerUps);
bitStream.Read(lifePowerUps);
bitStream.Read(armorPowerUps);
bitStream.Read(metersTraveled);
bitStream.Read(timesSmashed);
bitStream.Read(totalDamageTaken);
bitStream.Read(totalDamageHealed);
bitStream.Read(totalArmorRepaired);
bitStream.Read(totalImaginationRestored);
bitStream.Read(totalImaginationUsed);
bitStream.Read(distanceDriven);
bitStream.Read(timeAirborneInCar);
bitStream.Read(racingImaginationPowerUps);
bitStream.Read(racingImaginationCrates);
bitStream.Read(racingCarBoosts);
bitStream.Read(racingTimesWrecked);
bitStream.Read(racingSmashablesSmashed);
bitStream.Read(racesFinished);
bitStream.Read(firstPlaceRaces);
bitStream.Read(currencyCollected); // Verify the statistics we set
bitStream.Read(bricksCollected); EXPECT_EQ(currencyCollected, 100); // Value we set
bitStream.Read(smashablesSmashed); EXPECT_EQ(bricksCollected, 200); // Value we set
bitStream.Read(quickBuildsCompleted); EXPECT_EQ(smashablesSmashed, 50); // Value we set
bitStream.Read(enemiesSmashed); EXPECT_EQ(quickBuildsCompleted, 25); // Value we set
bitStream.Read(rocketsUsed); EXPECT_EQ(enemiesSmashed, 75); // Value we set
bitStream.Read(missionsCompleted);
bitStream.Read(petsTamed);
bitStream.Read(imaginationPowerUps);
bitStream.Read(lifePowerUps);
bitStream.Read(armorPowerUps);
bitStream.Read(metersTraveled);
bitStream.Read(timesSmashed);
bitStream.Read(totalDamageTaken);
bitStream.Read(totalDamageHealed);
bitStream.Read(totalArmorRepaired);
bitStream.Read(totalImaginationRestored);
bitStream.Read(totalImaginationUsed);
bitStream.Read(distanceDriven);
bitStream.Read(timeAirborneInCar);
bitStream.Read(racingImaginationPowerUps);
bitStream.Read(racingImaginationCrates);
bitStream.Read(racingCarBoosts);
bitStream.Read(racingTimesWrecked);
bitStream.Read(racingSmashablesSmashed);
bitStream.Read(racesFinished);
bitStream.Read(firstPlaceRaces);
ASSERT_GE(currencyCollected, 0); // Default statistics should be >= 0 // Default values for statistics we didn't set
ASSERT_GE(bricksCollected, 0); EXPECT_EQ(rocketsUsed, 0);
ASSERT_GE(smashablesSmashed, 0); EXPECT_EQ(missionsCompleted, 0);
ASSERT_GE(quickBuildsCompleted, 0); EXPECT_EQ(petsTamed, 0);
ASSERT_GE(enemiesSmashed, 0); EXPECT_EQ(imaginationPowerUps, 0);
ASSERT_GE(rocketsUsed, 0); EXPECT_EQ(lifePowerUps, 0);
ASSERT_GE(missionsCompleted, 0); EXPECT_EQ(armorPowerUps, 0);
ASSERT_GE(petsTamed, 0);
ASSERT_EQ(imaginationPowerUps, 0); // Default values // Read trailing construction data
ASSERT_EQ(lifePowerUps, 0); bool unknown1;
ASSERT_EQ(armorPowerUps, 0); bool isLanding;
bitStream.Read(unknown1);
bitStream.Read(isLanding);
EXPECT_FALSE(unknown1); // Default value
EXPECT_TRUE(isLanding); // Should be true when we have rocket config
if (isLanding) {
uint16_t rocketConfigSize;
bitStream.Read(rocketConfigSize);
EXPECT_GT(rocketConfigSize, 0); // Should have some config data
// Skip over rocket config data
for (uint16_t i = 0; i < rocketConfigSize; i++) {
uint16_t configChar;
bitStream.Read(configChar);
}
}
}
bitStream.Reset();
} }
/**
* Test serialization of a CharacterComponent update
*/
TEST_F(CharacterComponentTest, CharacterComponentSerializeUpdateTest) { TEST_F(CharacterComponentTest, CharacterComponentSerializeUpdateTest) {
// Test non-initial update serialization // Test non-initial update serialization
characterComponent->Serialize(bitStream, false); characterComponent->Serialize(bitStream, false);
// Should serialize flags for different update types {
bool hasLevel, hasSpeedBoost, hasClaimCodes, hasActivity; // Should serialize flags for different update types
bitStream.Read(hasLevel); bool hasGMInfo, hasCurrentActivity, hasSocialInfo;
bitStream.Read(hasSpeedBoost); bitStream.Read(hasGMInfo);
bitStream.Read(hasClaimCodes); bitStream.Read(hasCurrentActivity);
bitStream.Read(hasActivity); bitStream.Read(hasSocialInfo);
// Default state should have no updates // We set current activity, so that should be true
ASSERT_FALSE(hasLevel); EXPECT_TRUE(hasGMInfo); // PVP was enabled
ASSERT_FALSE(hasSpeedBoost); EXPECT_TRUE(hasCurrentActivity); // We set current activity
ASSERT_FALSE(hasClaimCodes); EXPECT_FALSE(hasSocialInfo); // Default state
ASSERT_FALSE(hasActivity);
} // Read GM info if present
if (hasGMInfo) {
TEST_F(CharacterComponentTest, CharacterComponentClaimCodeSerializationTest) { bool pvpEnabled, isGM;
// Test that default claim codes serialize correctly (all should be 0) uint8_t gmLevel;
characterComponent->Serialize(bitStream, true); bool editorEnabled;
uint8_t editorLevel;
bool hasClaimCode0, hasClaimCode1, hasClaimCode2, hasClaimCode3;
bitStream.Read(pvpEnabled);
bitStream.Read(hasClaimCode0); bitStream.Read(isGM);
ASSERT_FALSE(hasClaimCode0); // 0 should result in false bitStream.Read(gmLevel);
bitStream.Read(editorEnabled);
bitStream.Read(hasClaimCode1); bitStream.Read(editorLevel);
ASSERT_FALSE(hasClaimCode1); // 0 should result in false
EXPECT_TRUE(pvpEnabled); // Value we set
bitStream.Read(hasClaimCode2); EXPECT_FALSE(isGM); // Default value
ASSERT_FALSE(hasClaimCode2); // 0 should result in false EXPECT_EQ(gmLevel, 0); // Default GM level
EXPECT_FALSE(editorEnabled); // Default value
bitStream.Read(hasClaimCode3); EXPECT_EQ(editorLevel, 0); // Default editor level
ASSERT_FALSE(hasClaimCode3); // 0 should result in false }
// Read current activity if present
if (hasCurrentActivity) {
uint32_t currentActivity;
bitStream.Read(currentActivity);
EXPECT_EQ(currentActivity, static_cast<uint32_t>(eGameActivity::QUICKBUILDING)); // Value we set
}
// Social info should not be present in this test case
if (hasSocialInfo) {
// Skip social info reading as it's not expected to be present
FAIL() << "Social info should not be dirty in this test";
}
}
bitStream.Reset();
} }