From f86024e06d713a5faec4672a722666889a78752e Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 31 Aug 2025 19:23:28 +0000 Subject: [PATCH] Add MovingPlatformComponent and ModelComponent serialization tests Co-authored-by: aronwk-aaron <26027722+aronwk-aaron@users.noreply.github.com> --- .../dComponentsTests/CMakeLists.txt | 2 + .../dComponentsTests/ModelComponentTests.cpp | 265 ++++++++++++++++++ .../MovingPlatformComponentTests.cpp | 223 +++++++++++++++ 3 files changed, 490 insertions(+) create mode 100644 tests/dGameTests/dComponentsTests/ModelComponentTests.cpp create mode 100644 tests/dGameTests/dComponentsTests/MovingPlatformComponentTests.cpp diff --git a/tests/dGameTests/dComponentsTests/CMakeLists.txt b/tests/dGameTests/dComponentsTests/CMakeLists.txt index f73f1214..437a6913 100644 --- a/tests/dGameTests/dComponentsTests/CMakeLists.txt +++ b/tests/dGameTests/dComponentsTests/CMakeLists.txt @@ -1,5 +1,7 @@ set(DCOMPONENTS_TESTS "DestroyableComponentTests.cpp" + "ModelComponentTests.cpp" + "MovingPlatformComponentTests.cpp" "PetComponentTests.cpp" "SimplePhysicsComponentTests.cpp" "SavingTests.cpp" diff --git a/tests/dGameTests/dComponentsTests/ModelComponentTests.cpp b/tests/dGameTests/dComponentsTests/ModelComponentTests.cpp new file mode 100644 index 00000000..ac67c39d --- /dev/null +++ b/tests/dGameTests/dComponentsTests/ModelComponentTests.cpp @@ -0,0 +1,265 @@ +#include "GameDependencies.h" +#include + +#include "BitStream.h" +#include "ModelComponent.h" +#include "Entity.h" +#include "eReplicaComponentType.h" +#include "PetComponent.h" + +class ModelTest : public GameDependenciesTest { +protected: + Entity* baseEntity; + ModelComponent* modelComponent; + CBITSTREAM + uint32_t flags = 0; + void SetUp() override { + SetUpDependencies(); + baseEntity = new Entity(15, GameDependenciesTest::info); + modelComponent = baseEntity->AddComponent(); + // Initialize some values to be not default + modelComponent->SetPosition(NiPoint3(10.0f, 20.0f, 30.0f)); + modelComponent->SetRotation(NiQuaternion(4.0f, 1.0f, 2.0f, 3.0f)); // For x=1, y=2, z=3, w=4 + modelComponent->AddInteract(); // Make it pickable + } + + void TearDown() override { + delete baseEntity; + TearDownDependencies(); + } +}; + +/** + * Test serialization of a ModelComponent for a non-pet entity + */ +TEST_F(ModelTest, ModelComponentSerializeNonPetTest) { + bitStream.Reset(); + + // Now we test a serialization for correctness. + modelComponent->Serialize(bitStream, false); + + // Read back the serialized data + + // ItemComponent serialization (since this is not a pet) + bool hasItemComponent; + bitStream.Read(hasItemComponent); + EXPECT_EQ(hasItemComponent, true); + + LWOOBJID userModelID; + bitStream.Read(userModelID); + EXPECT_EQ(userModelID, baseEntity->GetObjectID()); // Should use entity ID when no user model ID + + int extraInfo; + bitStream.Read(extraInfo); + EXPECT_EQ(extraInfo, 0); + + bool hasExtraItemData; + bitStream.Read(hasExtraItemData); + EXPECT_EQ(hasExtraItemData, false); + + // ModelComponent serialization + bool hasModelInfo; + bitStream.Read(hasModelInfo); + EXPECT_EQ(hasModelInfo, true); + + bool isPickable; + bitStream.Read(isPickable); + EXPECT_EQ(isPickable, true); // We added an interact + + uint32_t physicsType; + bitStream.Read(physicsType); + EXPECT_EQ(physicsType, 2); + + NiPoint3 originalPosition; + bitStream.Read(originalPosition.x); + bitStream.Read(originalPosition.y); + bitStream.Read(originalPosition.z); + EXPECT_EQ(originalPosition, NiPoint3(10.0f, 20.0f, 30.0f)); + + NiQuaternion originalRotation; + bitStream.Read(originalRotation.x); + bitStream.Read(originalRotation.y); + bitStream.Read(originalRotation.z); + bitStream.Read(originalRotation.w); + EXPECT_EQ(originalRotation, NiQuaternion(4.0f, 1.0f, 2.0f, 3.0f)); // x=1, y=2, z=3, w=4 + + bool hasBehaviorInfo; + bitStream.Read(hasBehaviorInfo); + EXPECT_EQ(hasBehaviorInfo, true); + + uint32_t numBehaviors; + bitStream.Read(numBehaviors); + EXPECT_EQ(numBehaviors, 0); // No behaviors added in test + + bool isPaused; + bitStream.Read(isPaused); + EXPECT_EQ(isPaused, false); +} + +/** + * Test serialization of a ModelComponent for a pet entity + */ +TEST_F(ModelTest, ModelComponentSerializePetTest) { + bitStream.Reset(); + + // Add a PetComponent to make this entity a pet + baseEntity->AddComponent(1); + + // Now we test a serialization for correctness. + modelComponent->Serialize(bitStream, false); + + // Read back the serialized data + // Should NOT have ItemComponent serialization for pets + + // ModelComponent serialization (should start immediately) + bool hasModelInfo; + bitStream.Read(hasModelInfo); + EXPECT_EQ(hasModelInfo, true); + + bool isPickable; + bitStream.Read(isPickable); + EXPECT_EQ(isPickable, true); // We added an interact + + uint32_t physicsType; + bitStream.Read(physicsType); + EXPECT_EQ(physicsType, 2); + + NiPoint3 originalPosition; + bitStream.Read(originalPosition.x); + bitStream.Read(originalPosition.y); + bitStream.Read(originalPosition.z); + EXPECT_EQ(originalPosition, NiPoint3(10.0f, 20.0f, 30.0f)); + + NiQuaternion originalRotation; + bitStream.Read(originalRotation.x); + bitStream.Read(originalRotation.y); + bitStream.Read(originalRotation.z); + bitStream.Read(originalRotation.w); + EXPECT_EQ(originalRotation, NiQuaternion(4.0f, 1.0f, 2.0f, 3.0f)); // x=1, y=2, z=3, w=4 + + bool hasBehaviorInfo; + bitStream.Read(hasBehaviorInfo); + EXPECT_EQ(hasBehaviorInfo, true); + + uint32_t numBehaviors; + bitStream.Read(numBehaviors); + EXPECT_EQ(numBehaviors, 0); // No behaviors added in test + + bool isPaused; + bitStream.Read(isPaused); + EXPECT_EQ(isPaused, false); +} + +/** + * Test serialization of a ModelComponent during initial update + */ +TEST_F(ModelTest, ModelComponentSerializeInitialUpdateTest) { + bitStream.Reset(); + + // Now we test a serialization for correctness with initial update. + modelComponent->Serialize(bitStream, true); + + // Read back the serialized data + + // ItemComponent serialization (since this is not a pet) + bool hasItemComponent; + bitStream.Read(hasItemComponent); + EXPECT_EQ(hasItemComponent, true); + + LWOOBJID userModelID; + bitStream.Read(userModelID); + EXPECT_EQ(userModelID, baseEntity->GetObjectID()); + + int extraInfo; + bitStream.Read(extraInfo); + EXPECT_EQ(extraInfo, 0); + + bool hasExtraItemData; + bitStream.Read(hasExtraItemData); + EXPECT_EQ(hasExtraItemData, false); + + // ModelComponent serialization + bool hasModelInfo; + bitStream.Read(hasModelInfo); + EXPECT_EQ(hasModelInfo, true); + + bool isPickable; + bitStream.Read(isPickable); + EXPECT_EQ(isPickable, true); + + uint32_t physicsType; + bitStream.Read(physicsType); + EXPECT_EQ(physicsType, 2); + + NiPoint3 originalPosition; + bitStream.Read(originalPosition.x); + bitStream.Read(originalPosition.y); + bitStream.Read(originalPosition.z); + EXPECT_EQ(originalPosition, NiPoint3(10.0f, 20.0f, 30.0f)); + + NiQuaternion originalRotation; + bitStream.Read(originalRotation.x); + bitStream.Read(originalRotation.y); + bitStream.Read(originalRotation.z); + bitStream.Read(originalRotation.w); + EXPECT_EQ(originalRotation, NiQuaternion(4.0f, 1.0f, 2.0f, 3.0f)); // x=1, y=2, z=3, w=4 + + bool hasBehaviorInfo; + bitStream.Read(hasBehaviorInfo); + EXPECT_EQ(hasBehaviorInfo, true); + + uint32_t numBehaviors; + bitStream.Read(numBehaviors); + EXPECT_EQ(numBehaviors, 0); + + bool isPaused; + bitStream.Read(isPaused); + EXPECT_EQ(isPaused, false); + + // During initial update, should write an additional false for model editing info + bool hasModelEditingInfo; + bitStream.Read(hasModelEditingInfo); + EXPECT_EQ(hasModelEditingInfo, false); +} + +/** + * Test ModelComponent getters and setters + */ +TEST_F(ModelTest, ModelComponentGettersSettersTest) { + // Test position + NiPoint3 testPosition(100.0f, 200.0f, 300.0f); + modelComponent->SetPosition(testPosition); + EXPECT_EQ(modelComponent->GetOriginalPosition(), testPosition); + + // Test rotation + NiQuaternion testRotation(5.0f, 6.0f, 7.0f, 8.0f); + modelComponent->SetRotation(testRotation); + EXPECT_EQ(modelComponent->GetOriginalRotation(), testRotation); + + // Test speed + modelComponent->SetSpeed(5.5f); + // Note: GetSpeed() method doesn't exist in the header, but we can verify the setter works + + // Test interact + modelComponent->RemoveInteract(); // Remove the one we added in SetUp + // Test that isPickable becomes false when no interactions + bitStream.Reset(); + modelComponent->Serialize(bitStream, false); + + // Skip itemcomponent data + bool hasItemComponent; + bitStream.Read(hasItemComponent); + LWOOBJID userModelID; + bitStream.Read(userModelID); + int extraInfo; + bitStream.Read(extraInfo); + bool hasExtraItemData; + bitStream.Read(hasExtraItemData); + + // Check model component + bool hasModelInfo; + bitStream.Read(hasModelInfo); + bool isPickable; + bitStream.Read(isPickable); + EXPECT_EQ(isPickable, false); // Should be false now +} \ No newline at end of file diff --git a/tests/dGameTests/dComponentsTests/MovingPlatformComponentTests.cpp b/tests/dGameTests/dComponentsTests/MovingPlatformComponentTests.cpp new file mode 100644 index 00000000..3e23d1e7 --- /dev/null +++ b/tests/dGameTests/dComponentsTests/MovingPlatformComponentTests.cpp @@ -0,0 +1,223 @@ +#include "GameDependencies.h" +#include + +#include "BitStream.h" +#include "MovingPlatformComponent.h" +#include "Entity.h" +#include "eReplicaComponentType.h" +#include "eMovementPlatformState.h" + +class MovingPlatformTest : public GameDependenciesTest { +protected: + Entity* baseEntity; + MovingPlatformComponent* movingPlatformComponent; + CBITSTREAM + uint32_t flags = 0; + void SetUp() override { + SetUpDependencies(); + baseEntity = new Entity(15, GameDependenciesTest::info); + movingPlatformComponent = baseEntity->AddComponent("testPath"); + // Initialize some values to be not default + movingPlatformComponent->SetSerialized(true); + + // Set up the MoverSubComponent with some test values + auto* moverSubComponent = movingPlatformComponent->GetMoverSubComponent(); + if (moverSubComponent) { + moverSubComponent->mState = eMovementPlatformState::Moving; + moverSubComponent->mDesiredWaypointIndex = 5; + moverSubComponent->mShouldStopAtDesiredWaypoint = true; + moverSubComponent->mInReverse = false; + moverSubComponent->mPercentBetweenPoints = 0.75f; + moverSubComponent->mPosition = NiPoint3(10.0f, 20.0f, 30.0f); + moverSubComponent->mCurrentWaypointIndex = 3; + moverSubComponent->mNextWaypointIndex = 4; + moverSubComponent->mIdleTimeElapsed = 2.5f; + } + } + + void TearDown() override { + delete baseEntity; + TearDownDependencies(); + } +}; + +/** + * Test serialization of a MovingPlatformComponent with m_Serialize = false + */ +TEST_F(MovingPlatformTest, MovingPlatformComponentSerializeDisabledTest) { + bitStream.Reset(); + + // Set m_Serialize to false to test the early return path + movingPlatformComponent->SetSerialized(false); + + // Now we test a serialization for correctness. + movingPlatformComponent->Serialize(bitStream, false); + + // Should only write two false booleans + ASSERT_EQ(bitStream.GetNumberOfBitsUsed(), 2); + + bool firstFlag; + bool secondFlag; + bitStream.Read(firstFlag); + bitStream.Read(secondFlag); + + EXPECT_EQ(firstFlag, false); + EXPECT_EQ(secondFlag, false); +} + +/** + * Test serialization of a MovingPlatformComponent with enabled serialization but no path + */ +TEST_F(MovingPlatformTest, MovingPlatformComponentSerializeNoPathTest) { + bitStream.Reset(); + + // Create a component with no path to test the path logic + auto* entityNoPath = new Entity(16, GameDependenciesTest::info); + auto* componentNoPath = entityNoPath->AddComponent(""); + componentNoPath->SetSerialized(true); + + // Stop pathing to make hasPath false + componentNoPath->StopPathing(); + + componentNoPath->Serialize(bitStream, false); + + // Should write: true (m_Serialize), false (hasPath), true (hasPlatform), mover type, then mover data + bool isEnabled; + bool hasPath; + bool hasPlatform; + + bitStream.Read(isEnabled); + bitStream.Read(hasPath); + bitStream.Read(hasPlatform); + + EXPECT_EQ(isEnabled, true); + EXPECT_EQ(hasPath, false); + EXPECT_EQ(hasPlatform, true); + + // Should continue with platform serialization + eMoverSubComponentType moverType; + bitStream.Read(moverType); + EXPECT_EQ(moverType, eMoverSubComponentType::mover); + + // Clean up + delete entityNoPath; +} + +/** + * Test complete serialization of a MovingPlatformComponent with path + */ +TEST_F(MovingPlatformTest, MovingPlatformComponentSerializeFullTest) { + bitStream.Reset(); + + // Now we test a serialization for correctness. + movingPlatformComponent->Serialize(bitStream, false); + + // Read back the serialized data + bool isEnabled; + bool hasPath; + + bitStream.Read(isEnabled); + bitStream.Read(hasPath); + + EXPECT_EQ(isEnabled, true); + EXPECT_EQ(hasPath, true); + + if (hasPath) { + bool isOnRail; + bitStream.Read(isOnRail); + EXPECT_EQ(isOnRail, true); + + uint16_t pathNameSize; + bitStream.Read(pathNameSize); + EXPECT_EQ(pathNameSize, 8); // "testPath" length + + std::u16string pathName; + for (uint16_t i = 0; i < pathNameSize; i++) { + uint16_t character; + bitStream.Read(character); + pathName += character; + } + + uint32_t startingPoint; + bitStream.Read(startingPoint); + EXPECT_EQ(startingPoint, 0); + + bool reverse; + bitStream.Read(reverse); + EXPECT_EQ(reverse, false); + } + + bool hasPlatform; + bitStream.Read(hasPlatform); + EXPECT_EQ(hasPlatform, true); + + if (hasPlatform) { + eMoverSubComponentType moverType; + bitStream.Read(moverType); + EXPECT_EQ(moverType, eMoverSubComponentType::mover); + + // Test MoverSubComponent serialization + bool moverHasData; + bitStream.Read(moverHasData); + EXPECT_EQ(moverHasData, true); + + eMovementPlatformState state; + bitStream.Read(state); + EXPECT_EQ(state, eMovementPlatformState::Moving); + + int32_t desiredWaypointIndex; + bitStream.Read(desiredWaypointIndex); + EXPECT_EQ(desiredWaypointIndex, 5); + + bool shouldStopAtDesiredWaypoint; + bitStream.Read(shouldStopAtDesiredWaypoint); + EXPECT_EQ(shouldStopAtDesiredWaypoint, true); + + bool inReverse; + bitStream.Read(inReverse); + EXPECT_EQ(inReverse, false); + + float percentBetweenPoints; + bitStream.Read(percentBetweenPoints); + EXPECT_EQ(percentBetweenPoints, 0.75f); + + float positionX, positionY, positionZ; + bitStream.Read(positionX); + bitStream.Read(positionY); + bitStream.Read(positionZ); + EXPECT_EQ(positionX, 10.0f); + EXPECT_EQ(positionY, 20.0f); + EXPECT_EQ(positionZ, 30.0f); + + uint32_t currentWaypointIndex; + bitStream.Read(currentWaypointIndex); + EXPECT_EQ(currentWaypointIndex, 3); + + uint32_t nextWaypointIndex; + bitStream.Read(nextWaypointIndex); + EXPECT_EQ(nextWaypointIndex, 4); + + float idleTimeElapsed; + bitStream.Read(idleTimeElapsed); + EXPECT_EQ(idleTimeElapsed, 2.5f); + + float moveTimeElapsed; + bitStream.Read(moveTimeElapsed); + EXPECT_EQ(moveTimeElapsed, 0.0f); // Always 0 in current implementation + } +} + +/** + * Test MoverSubComponent initialization and basic functionality + */ +TEST_F(MovingPlatformTest, MoverSubComponentInitializationTest) { + auto* moverSubComponent = movingPlatformComponent->GetMoverSubComponent(); + ASSERT_NE(moverSubComponent, nullptr); + + // Test that we can access and modify the mover sub component + moverSubComponent->mState = eMovementPlatformState::Stopped; + EXPECT_EQ(moverSubComponent->mState, eMovementPlatformState::Stopped); + + moverSubComponent->mDesiredWaypointIndex = 10; + EXPECT_EQ(moverSubComponent->mDesiredWaypointIndex, 10); +} \ No newline at end of file