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,38 +33,49 @@ 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 // Read back the serialized data to verify structure
bool hasClaimCode0; bool hasClaimCode0, hasClaimCode1, hasClaimCode2, hasClaimCode3;
bitStream.Read(hasClaimCode0); bitStream.Read(hasClaimCode0);
ASSERT_FALSE(hasClaimCode0); // Default is 0
bool hasClaimCode1;
bitStream.Read(hasClaimCode1); bitStream.Read(hasClaimCode1);
ASSERT_FALSE(hasClaimCode1); // Default is 0
bool hasClaimCode2;
bitStream.Read(hasClaimCode2); bitStream.Read(hasClaimCode2);
ASSERT_FALSE(hasClaimCode2); // Default is 0
bool hasClaimCode3;
bitStream.Read(hasClaimCode3); bitStream.Read(hasClaimCode3);
ASSERT_FALSE(hasClaimCode3); // Default is 0
EXPECT_FALSE(hasClaimCode0); // Default is 0
EXPECT_FALSE(hasClaimCode1); // Default is 0
EXPECT_FALSE(hasClaimCode2); // Default is 0
EXPECT_FALSE(hasClaimCode3); // Default is 0
// Character appearance data // Character appearance data
uint32_t hairColor, hairStyle, head, shirtColor, pantsColor, shirtStyle, headColor; uint32_t hairColor, hairStyle, head, shirtColor, pantsColor, shirtStyle, headColor;
@@ -88,24 +99,26 @@ TEST_F(CharacterComponentTest, CharacterComponentSerializeConstructionTest) {
bitStream.Read(uScore); bitStream.Read(uScore);
bitStream.Read(freeToPlay); bitStream.Read(freeToPlay);
ASSERT_EQ(hairColor, 5); // Verify character appearance values
ASSERT_EQ(hairStyle, 10); EXPECT_EQ(hairColor, 5);
ASSERT_EQ(head, 0); EXPECT_EQ(hairStyle, 10);
ASSERT_EQ(shirtColor, 15); EXPECT_EQ(head, 0); // Default value
ASSERT_EQ(pantsColor, 20); EXPECT_EQ(shirtColor, 15);
ASSERT_EQ(shirtStyle, 25); EXPECT_EQ(pantsColor, 20);
ASSERT_EQ(headColor, 0); EXPECT_EQ(shirtStyle, 25);
ASSERT_EQ(eyebrows, 3); EXPECT_EQ(headColor, 0); // Default value
ASSERT_EQ(eyes, 7); EXPECT_EQ(eyebrows, 3);
ASSERT_EQ(mouth, 9); EXPECT_EQ(eyes, 7);
// Account ID and other values are set internally EXPECT_EQ(mouth, 9);
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 // Account and score values
EXPECT_GE(accountId, 0); // Valid account ID
EXPECT_GE(lastLogin, 0); // Valid last login
EXPECT_EQ(propModLastDisplayTime, 0); // Default value
EXPECT_EQ(uScore, 12345); // Value we set
EXPECT_FALSE(freeToPlay); // Default value
// Statistics verification - read all statistics values
uint64_t currencyCollected, bricksCollected, smashablesSmashed, quickBuildsCompleted; uint64_t currencyCollected, bricksCollected, smashablesSmashed, quickBuildsCompleted;
uint64_t enemiesSmashed, rocketsUsed, missionsCompleted, petsTamed; uint64_t enemiesSmashed, rocketsUsed, missionsCompleted, petsTamed;
uint64_t imaginationPowerUps, lifePowerUps, armorPowerUps, metersTraveled; uint64_t imaginationPowerUps, lifePowerUps, armorPowerUps, metersTraveled;
@@ -142,52 +155,96 @@ TEST_F(CharacterComponentTest, CharacterComponentSerializeConstructionTest) {
bitStream.Read(racesFinished); bitStream.Read(racesFinished);
bitStream.Read(firstPlaceRaces); bitStream.Read(firstPlaceRaces);
ASSERT_GE(currencyCollected, 0); // Default statistics should be >= 0 // Verify the statistics we set
ASSERT_GE(bricksCollected, 0); EXPECT_EQ(currencyCollected, 100); // Value we set
ASSERT_GE(smashablesSmashed, 0); EXPECT_EQ(bricksCollected, 200); // Value we set
ASSERT_GE(quickBuildsCompleted, 0); EXPECT_EQ(smashablesSmashed, 50); // Value we set
ASSERT_GE(enemiesSmashed, 0); EXPECT_EQ(quickBuildsCompleted, 25); // Value we set
ASSERT_GE(rocketsUsed, 0); EXPECT_EQ(enemiesSmashed, 75); // Value we set
ASSERT_GE(missionsCompleted, 0);
ASSERT_GE(petsTamed, 0); // Default values for statistics we didn't set
ASSERT_EQ(imaginationPowerUps, 0); // Default values EXPECT_EQ(rocketsUsed, 0);
ASSERT_EQ(lifePowerUps, 0); EXPECT_EQ(missionsCompleted, 0);
ASSERT_EQ(armorPowerUps, 0); EXPECT_EQ(petsTamed, 0);
EXPECT_EQ(imaginationPowerUps, 0);
EXPECT_EQ(lifePowerUps, 0);
EXPECT_EQ(armorPowerUps, 0);
// Read trailing construction data
bool unknown1;
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 // Should serialize flags for different update types
bool hasLevel, hasSpeedBoost, hasClaimCodes, hasActivity; bool hasGMInfo, hasCurrentActivity, hasSocialInfo;
bitStream.Read(hasLevel); bitStream.Read(hasGMInfo);
bitStream.Read(hasSpeedBoost); bitStream.Read(hasCurrentActivity);
bitStream.Read(hasClaimCodes); bitStream.Read(hasSocialInfo);
bitStream.Read(hasActivity);
// 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) {
bool pvpEnabled, isGM;
uint8_t gmLevel;
bool editorEnabled;
uint8_t editorLevel;
bitStream.Read(pvpEnabled);
bitStream.Read(isGM);
bitStream.Read(gmLevel);
bitStream.Read(editorEnabled);
bitStream.Read(editorLevel);
EXPECT_TRUE(pvpEnabled); // Value we set
EXPECT_FALSE(isGM); // Default value
EXPECT_EQ(gmLevel, 0); // Default GM level
EXPECT_FALSE(editorEnabled); // Default value
EXPECT_EQ(editorLevel, 0); // Default editor level
} }
TEST_F(CharacterComponentTest, CharacterComponentClaimCodeSerializationTest) { // Read current activity if present
// Test that default claim codes serialize correctly (all should be 0) if (hasCurrentActivity) {
characterComponent->Serialize(bitStream, true); uint32_t currentActivity;
bitStream.Read(currentActivity);
bool hasClaimCode0, hasClaimCode1, hasClaimCode2, hasClaimCode3; EXPECT_EQ(currentActivity, static_cast<uint32_t>(eGameActivity::QUICKBUILDING)); // Value we set
}
bitStream.Read(hasClaimCode0);
ASSERT_FALSE(hasClaimCode0); // 0 should result in false // Social info should not be present in this test case
if (hasSocialInfo) {
bitStream.Read(hasClaimCode1); // Skip social info reading as it's not expected to be present
ASSERT_FALSE(hasClaimCode1); // 0 should result in false FAIL() << "Social info should not be dirty in this test";
}
bitStream.Read(hasClaimCode2); }
ASSERT_FALSE(hasClaimCode2); // 0 should result in false bitStream.Reset();
bitStream.Read(hasClaimCode3);
ASSERT_FALSE(hasClaimCode3); // 0 should result in false
} }