diff --git a/dDatabase/GameDatabase/CMakeLists.txt b/dDatabase/GameDatabase/CMakeLists.txt index 09ca7251..32fe414a 100644 --- a/dDatabase/GameDatabase/CMakeLists.txt +++ b/dDatabase/GameDatabase/CMakeLists.txt @@ -8,9 +8,15 @@ foreach(file ${DDATABSE_DATABSES_MYSQL_SOURCES}) set(DDATABASE_GAMEDATABASE_SOURCES ${DDATABASE_GAMEDATABASE_SOURCES} "MySQL/${file}") endforeach() +add_subdirectory(TestSQL) + +foreach(file ${DDATABSE_DATABSES_TEST_SQL_SOURCES}) + set(DDATABASE_GAMEDATABASE_SOURCES ${DDATABASE_GAMEDATABASE_SOURCES} "TestSQL/${file}") +endforeach() + add_library(dDatabaseGame STATIC ${DDATABASE_GAMEDATABASE_SOURCES}) target_include_directories(dDatabaseGame PUBLIC "." - "ITables" PRIVATE "MySQL" + "ITables" PRIVATE "MySQL" "TestSQL" "${PROJECT_SOURCE_DIR}/dCommon" "${PROJECT_SOURCE_DIR}/dCommon/dEnums" ) diff --git a/dDatabase/GameDatabase/Database.cpp b/dDatabase/GameDatabase/Database.cpp index cb4f989a..fef9ab39 100644 --- a/dDatabase/GameDatabase/Database.cpp +++ b/dDatabase/GameDatabase/Database.cpp @@ -38,3 +38,8 @@ void Database::Destroy(std::string source) { LOG("Trying to destroy database when it's not connected!"); } } + +void Database::_setDatabase(GameDatabase* const db) { + if (database) delete database; + database = db; +} diff --git a/dDatabase/GameDatabase/Database.h b/dDatabase/GameDatabase/Database.h index 3eb292d1..65b04722 100644 --- a/dDatabase/GameDatabase/Database.h +++ b/dDatabase/GameDatabase/Database.h @@ -9,4 +9,8 @@ namespace Database { void Connect(); GameDatabase* Get(); void Destroy(std::string source = ""); + + // Used for assigning a test database as the handler for database logic. + // Do not use in production code. + void _setDatabase(GameDatabase* const db); }; diff --git a/dDatabase/GameDatabase/TestSQL/CMakeLists.txt b/dDatabase/GameDatabase/TestSQL/CMakeLists.txt new file mode 100644 index 00000000..cf07f419 --- /dev/null +++ b/dDatabase/GameDatabase/TestSQL/CMakeLists.txt @@ -0,0 +1,4 @@ +SET(DDATABSE_DATABSES_TEST_SQL_SOURCES + "TestSQLDatabase.cpp" + PARENT_SCOPE +) diff --git a/dDatabase/GameDatabase/TestSQL/TestSQLDatabase.cpp b/dDatabase/GameDatabase/TestSQL/TestSQLDatabase.cpp new file mode 100644 index 00000000..e44cd1f7 --- /dev/null +++ b/dDatabase/GameDatabase/TestSQL/TestSQLDatabase.cpp @@ -0,0 +1,306 @@ +#include "TestSQLDatabase.h" + +void TestSQLDatabase::Connect() { + +} + +void TestSQLDatabase::Destroy(std::string source) { + +} + +sql::PreparedStatement* TestSQLDatabase::CreatePreppedStmt(const std::string& query) { + return nullptr; +} + +void TestSQLDatabase::Commit() { + +} + +bool TestSQLDatabase::GetAutoCommit() { + return {}; +} + +void TestSQLDatabase::SetAutoCommit(bool value) { + +} + +void TestSQLDatabase::ExecuteCustomQuery(const std::string_view query) { + +} + +std::optional TestSQLDatabase::GetMasterInfo() { + return {}; +} + +std::vector TestSQLDatabase::GetApprovedCharacterNames() { + return {}; +} + +std::vector TestSQLDatabase::GetFriendsList(uint32_t charID) { + return {}; +} + +std::optional TestSQLDatabase::GetBestFriendStatus(const uint32_t playerCharacterId, const uint32_t friendCharacterId) { + return {}; +} + +void TestSQLDatabase::SetBestFriendStatus(const uint32_t playerAccountId, const uint32_t friendAccountId, const uint32_t bestFriendStatus) { + +} + +void TestSQLDatabase::AddFriend(const uint32_t playerAccountId, const uint32_t friendAccountId) { + +} + +void TestSQLDatabase::RemoveFriend(const uint32_t playerAccountId, const uint32_t friendAccountId) { + +} + +void TestSQLDatabase::UpdateActivityLog(const uint32_t characterId, const eActivityType activityType, const LWOMAPID mapId) { + +} + +void TestSQLDatabase::DeleteUgcModelData(const LWOOBJID& modelId) { + +} + +void TestSQLDatabase::UpdateUgcModelData(const LWOOBJID& modelId, std::istringstream& lxfml) { + +} + +std::vector TestSQLDatabase::GetAllUgcModels() { + return {}; +} + +void TestSQLDatabase::CreateMigrationHistoryTable() { + +} + +bool TestSQLDatabase::IsMigrationRun(const std::string_view str) { + return {}; +} + +void TestSQLDatabase::InsertMigration(const std::string_view str) { + +} + +std::optional TestSQLDatabase::GetCharacterInfo(const uint32_t charId) { + return {}; +} + +std::optional TestSQLDatabase::GetCharacterInfo(const std::string_view charId) { + return {}; +} + +std::string TestSQLDatabase::GetCharacterXml(const uint32_t accountId) { + return {}; +} + +void TestSQLDatabase::UpdateCharacterXml(const uint32_t characterId, const std::string_view lxfml) { + +} + +std::optional TestSQLDatabase::GetAccountInfo(const std::string_view username) { + return {}; +} + +void TestSQLDatabase::InsertNewCharacter(const ICharInfo::Info info) { + +} + +void TestSQLDatabase::InsertCharacterXml(const uint32_t accountId, const std::string_view lxfml) { + +} + +std::vector TestSQLDatabase::GetAccountCharacterIds(uint32_t accountId) { + return {}; +} + +void TestSQLDatabase::DeleteCharacter(const uint32_t characterId) { + +} + +void TestSQLDatabase::SetCharacterName(const uint32_t characterId, const std::string_view name) { + +} + +void TestSQLDatabase::SetPendingCharacterName(const uint32_t characterId, const std::string_view name) { + +} + +void TestSQLDatabase::UpdateLastLoggedInCharacter(const uint32_t characterId) { + +} + +void TestSQLDatabase::SetPetNameModerationStatus(const LWOOBJID& petId, const IPetNames::Info& info) { + +} + +std::optional TestSQLDatabase::GetPetNameInfo(const LWOOBJID& petId) { + return {}; +} + +std::optional TestSQLDatabase::GetPropertyInfo(const LWOMAPID mapId, const LWOCLONEID cloneId) { + return {}; +} + +void TestSQLDatabase::UpdatePropertyModerationInfo(const IProperty::Info& info) { + +} + +void TestSQLDatabase::UpdatePropertyDetails(const IProperty::Info& info) { + +} + +void TestSQLDatabase::InsertNewProperty(const IProperty::Info& info, const uint32_t templateId, const LWOZONEID& zoneId) { + +} + +std::vector TestSQLDatabase::GetPropertyModels(const LWOOBJID& propertyId) { + return {}; +} + +void TestSQLDatabase::RemoveUnreferencedUgcModels() { + +} + +void TestSQLDatabase::InsertNewPropertyModel(const LWOOBJID& propertyId, const IPropertyContents::Model& model, const std::string_view name) { + +} + +void TestSQLDatabase::UpdateModel(const LWOOBJID& propertyId, const NiPoint3& position, const NiQuaternion& rotation, const std::array, 5>& behaviors) { + +} + +void TestSQLDatabase::RemoveModel(const LWOOBJID& modelId) { + +} + +void TestSQLDatabase::UpdatePerformanceCost(const LWOZONEID& zoneId, const float performanceCost) { + +} + +void TestSQLDatabase::InsertNewBugReport(const IBugReports::Info& info) { + +} + +void TestSQLDatabase::InsertCheatDetection(const IPlayerCheatDetections::Info& info) { + +} + +void TestSQLDatabase::InsertNewMail(const IMail::MailInfo& mail) { + +} + +void TestSQLDatabase::InsertNewUgcModel(std::istringstream& sd0Data, const uint32_t blueprintId, const uint32_t accountId, const uint32_t characterId) { + +} + +std::vector TestSQLDatabase::GetMailForPlayer(const uint32_t characterId, const uint32_t numberOfMail) { + return {}; +} + +std::optional TestSQLDatabase::GetMail(const uint64_t mailId) { + return {}; +} + +uint32_t TestSQLDatabase::GetUnreadMailCount(const uint32_t characterId) { + return {}; +} + +void TestSQLDatabase::MarkMailRead(const uint64_t mailId) { + +} + +void TestSQLDatabase::DeleteMail(const uint64_t mailId) { + +} + +void TestSQLDatabase::ClaimMailItem(const uint64_t mailId) { + +} + +void TestSQLDatabase::InsertSlashCommandUsage(const uint32_t characterId, const std::string_view command) { + +} + +void TestSQLDatabase::UpdateAccountUnmuteTime(const uint32_t accountId, const uint64_t timeToUnmute) { + +} + +void TestSQLDatabase::UpdateAccountBan(const uint32_t accountId, const bool banned) { + +} + +void TestSQLDatabase::UpdateAccountPassword(const uint32_t accountId, const std::string_view bcryptpassword) { + +} + +void TestSQLDatabase::InsertNewAccount(const std::string_view username, const std::string_view bcryptpassword) { + +} + +void TestSQLDatabase::SetMasterIp(const std::string_view ip, const uint32_t port) { + +} + +std::optional TestSQLDatabase::GetCurrentPersistentId() { + return {}; +} + +void TestSQLDatabase::InsertDefaultPersistentId() { + +} + +void TestSQLDatabase::UpdatePersistentId(const uint32_t id) { + +} + +std::optional TestSQLDatabase::GetDonationTotal(const uint32_t activityId) { + return {}; +} + +std::optional TestSQLDatabase::IsPlaykeyActive(const int32_t playkeyId) { + return {}; +} + +std::vector TestSQLDatabase::GetUgcModels(const LWOOBJID& propertyId) { + return {}; +} + +void TestSQLDatabase::AddIgnore(const uint32_t playerId, const uint32_t ignoredPlayerId) { + +} + +void TestSQLDatabase::RemoveIgnore(const uint32_t playerId, const uint32_t ignoredPlayerId) { + +} + +std::vector TestSQLDatabase::GetIgnoreList(const uint32_t playerId) { + return {}; +} + +void TestSQLDatabase::InsertRewardCode(const uint32_t account_id, const uint32_t reward_code) { + +} + +std::vector TestSQLDatabase::GetRewardCodesByAccountID(const uint32_t account_id) { + return {}; +} + +void TestSQLDatabase::AddBehavior(const IBehaviors::Info& info) { + +} + +std::string TestSQLDatabase::GetBehavior(const int32_t behaviorId) { + return {}; +} + +void TestSQLDatabase::RemoveBehavior(const int32_t behaviorId) { + +} + +void TestSQLDatabase::UpdateAccountGmLevel(const uint32_t accountId, const eGameMasterLevel gmLevel) { + +} + diff --git a/dDatabase/GameDatabase/TestSQL/TestSQLDatabase.h b/dDatabase/GameDatabase/TestSQL/TestSQLDatabase.h new file mode 100644 index 00000000..6fbdf879 --- /dev/null +++ b/dDatabase/GameDatabase/TestSQL/TestSQLDatabase.h @@ -0,0 +1,95 @@ +#ifndef TESTSQLDATABASE_H +#define TESTSQLDATABASE_H + +#include "GameDatabase.h" + +class TestSQLDatabase : public GameDatabase { + void Connect() override; + void Destroy(std::string source = "") override; + + sql::PreparedStatement* CreatePreppedStmt(const std::string& query) override; + void Commit() override; + bool GetAutoCommit() override; + void SetAutoCommit(bool value) override; + void ExecuteCustomQuery(const std::string_view query) override; + + // Overloaded queries + std::optional GetMasterInfo() override; + + std::vector GetApprovedCharacterNames() override; + + std::vector GetFriendsList(uint32_t charID) override; + + std::optional GetBestFriendStatus(const uint32_t playerCharacterId, const uint32_t friendCharacterId) override; + void SetBestFriendStatus(const uint32_t playerAccountId, const uint32_t friendAccountId, const uint32_t bestFriendStatus) override; + void AddFriend(const uint32_t playerAccountId, const uint32_t friendAccountId) override; + void RemoveFriend(const uint32_t playerAccountId, const uint32_t friendAccountId) override; + void UpdateActivityLog(const uint32_t characterId, const eActivityType activityType, const LWOMAPID mapId) override; + void DeleteUgcModelData(const LWOOBJID& modelId) override; + void UpdateUgcModelData(const LWOOBJID& modelId, std::istringstream& lxfml) override; + std::vector GetAllUgcModels() override; + void CreateMigrationHistoryTable() override; + bool IsMigrationRun(const std::string_view str) override; + void InsertMigration(const std::string_view str) override; + std::optional GetCharacterInfo(const uint32_t charId) override; + std::optional GetCharacterInfo(const std::string_view charId) override; + std::string GetCharacterXml(const uint32_t accountId) override; + void UpdateCharacterXml(const uint32_t characterId, const std::string_view lxfml) override; + std::optional GetAccountInfo(const std::string_view username) override; + void InsertNewCharacter(const ICharInfo::Info info) override; + void InsertCharacterXml(const uint32_t accountId, const std::string_view lxfml) override; + std::vector GetAccountCharacterIds(uint32_t accountId) override; + void DeleteCharacter(const uint32_t characterId) override; + void SetCharacterName(const uint32_t characterId, const std::string_view name) override; + void SetPendingCharacterName(const uint32_t characterId, const std::string_view name) override; + void UpdateLastLoggedInCharacter(const uint32_t characterId) override; + void SetPetNameModerationStatus(const LWOOBJID& petId, const IPetNames::Info& info) override; + std::optional GetPetNameInfo(const LWOOBJID& petId) override; + std::optional GetPropertyInfo(const LWOMAPID mapId, const LWOCLONEID cloneId) override; + void UpdatePropertyModerationInfo(const IProperty::Info& info) override; + void UpdatePropertyDetails(const IProperty::Info& info) override; + void InsertNewProperty(const IProperty::Info& info, const uint32_t templateId, const LWOZONEID& zoneId) override; + std::vector GetPropertyModels(const LWOOBJID& propertyId) override; + void RemoveUnreferencedUgcModels() override; + void InsertNewPropertyModel(const LWOOBJID& propertyId, const IPropertyContents::Model& model, const std::string_view name) override; + void UpdateModel(const LWOOBJID& propertyId, const NiPoint3& position, const NiQuaternion& rotation, const std::array, 5>& behaviors) override; + void RemoveModel(const LWOOBJID& modelId) override; + void UpdatePerformanceCost(const LWOZONEID& zoneId, const float performanceCost) override; + void InsertNewBugReport(const IBugReports::Info& info) override; + void InsertCheatDetection(const IPlayerCheatDetections::Info& info) override; + void InsertNewMail(const IMail::MailInfo& mail) override; + void InsertNewUgcModel( + std::istringstream& sd0Data, + const uint32_t blueprintId, + const uint32_t accountId, + const uint32_t characterId) override; + std::vector GetMailForPlayer(const uint32_t characterId, const uint32_t numberOfMail) override; + std::optional GetMail(const uint64_t mailId) override; + uint32_t GetUnreadMailCount(const uint32_t characterId) override; + void MarkMailRead(const uint64_t mailId) override; + void DeleteMail(const uint64_t mailId) override; + void ClaimMailItem(const uint64_t mailId) override; + void InsertSlashCommandUsage(const uint32_t characterId, const std::string_view command) override; + void UpdateAccountUnmuteTime(const uint32_t accountId, const uint64_t timeToUnmute) override; + void UpdateAccountBan(const uint32_t accountId, const bool banned) override; + void UpdateAccountPassword(const uint32_t accountId, const std::string_view bcryptpassword) override; + void InsertNewAccount(const std::string_view username, const std::string_view bcryptpassword) override; + void SetMasterIp(const std::string_view ip, const uint32_t port) override; + std::optional GetCurrentPersistentId() override; + void InsertDefaultPersistentId() override; + void UpdatePersistentId(const uint32_t id) override; + std::optional GetDonationTotal(const uint32_t activityId) override; + std::optional IsPlaykeyActive(const int32_t playkeyId) override; + std::vector GetUgcModels(const LWOOBJID& propertyId) override; + void AddIgnore(const uint32_t playerId, const uint32_t ignoredPlayerId) override; + void RemoveIgnore(const uint32_t playerId, const uint32_t ignoredPlayerId) override; + std::vector GetIgnoreList(const uint32_t playerId) override; + void InsertRewardCode(const uint32_t account_id, const uint32_t reward_code) override; + std::vector GetRewardCodesByAccountID(const uint32_t account_id) override; + void AddBehavior(const IBehaviors::Info& info) override; + std::string GetBehavior(const int32_t behaviorId) override; + void RemoveBehavior(const int32_t behaviorId) override; + void UpdateAccountGmLevel(const uint32_t accountId, const eGameMasterLevel gmLevel) override; +}; + +#endif //!TESTSQLDATABASE_H diff --git a/dGame/Character.cpp b/dGame/Character.cpp index 6c98fd85..2e62dae8 100644 --- a/dGame/Character.cpp +++ b/dGame/Character.cpp @@ -40,8 +40,8 @@ void Character::UpdateInfoFromDatabase() { auto charInfo = Database::Get()->GetCharacterInfo(m_ID); if (charInfo) { - m_Name = charInfo->name; - m_UnapprovedName = charInfo->pendingName; + m_Name = charInfo->name; + m_UnapprovedName = charInfo->pendingName; m_NameRejected = charInfo->needsRename; m_PropertyCloneID = charInfo->cloneId; m_PermissionMap = charInfo->permissionMap; diff --git a/dGame/Character.h b/dGame/Character.h index 7a83325b..0f41c634 100644 --- a/dGame/Character.h +++ b/dGame/Character.h @@ -38,6 +38,7 @@ public: const std::string& GetXMLData() const { return m_XMLData; } const tinyxml2::XMLDocument& GetXMLDoc() const { return m_Doc; } + void _setXmlDoc(tinyxml2::XMLDocument& doc) { doc.DeepCopy(&m_Doc); } /** * Out of abundance of safety and clarity of what this saves, this is its own function. @@ -459,6 +460,10 @@ public: User* GetParentUser() const { return m_ParentUser; } + void _doQuickXMLDataParse() { DoQuickXMLDataParse(); } + + void _setXmlData(const std::string& xmlData) { m_XMLData = xmlData; } + private: void UpdateInfoFromDatabase(); /** diff --git a/dGame/dComponents/CharacterComponent.h b/dGame/dComponents/CharacterComponent.h index 7e63b0bd..c8cfa988 100644 --- a/dGame/dComponents/CharacterComponent.h +++ b/dGame/dComponents/CharacterComponent.h @@ -25,6 +25,8 @@ struct ZoneStatistics { uint64_t m_CoinsCollected; uint64_t m_EnemiesSmashed; uint64_t m_QuickBuildsCompleted; + + bool operator==(const ZoneStatistics& rhs) const = default; }; /** @@ -279,9 +281,9 @@ public: */ void UpdateClientMinimap(bool showFaction, std::string ventureVisionType) const; - void SetCurrentInteracting(LWOOBJID objectID) {m_CurrentInteracting = objectID;}; + void SetCurrentInteracting(LWOOBJID objectID) { m_CurrentInteracting = objectID; }; - LWOOBJID GetCurrentInteracting() {return m_CurrentInteracting;}; + LWOOBJID GetCurrentInteracting() { return m_CurrentInteracting; }; /** * Sends a player to another zone with an optional clone ID @@ -307,6 +309,14 @@ public: void SetDroppedCoins(const uint64_t value) { m_DroppedCoins = value; }; + const std::array& GetClaimCodes() const { return m_ClaimCodes; }; + + const std::map& GetZoneStatistics() const { return m_ZoneStatistics; }; + + const std::u16string& GetLastRocketConfig() const { return m_LastRocketConfig; }; + + uint64_t GetTotalTimePlayed() const { return m_TotalTimePlayed; }; + /** * Character info regarding this character, including clothing styles, etc. */ diff --git a/dNet/dServer.h b/dNet/dServer.h index 40f606f1..f958fc40 100644 --- a/dNet/dServer.h +++ b/dNet/dServer.h @@ -86,7 +86,7 @@ private: void SetupForMasterConnection(); bool ConnectToMaster(); -private: +protected: Logger* mLogger = nullptr; dConfig* mConfig = nullptr; RakPeerInterface* mPeer = nullptr; diff --git a/tests/dGameTests/CMakeLists.txt b/tests/dGameTests/CMakeLists.txt index 58f213e0..e1c29433 100644 --- a/tests/dGameTests/CMakeLists.txt +++ b/tests/dGameTests/CMakeLists.txt @@ -9,6 +9,7 @@ add_subdirectory(dGameMessagesTests) list(APPEND DGAMETEST_SOURCES ${DGAMEMESSAGES_TESTS}) file(COPY ${GAMEMESSAGE_TESTBITSTREAMS} DESTINATION ${CMAKE_CURRENT_BINARY_DIR}) +file(COPY ${COMPONENT_TEST_DATA} DESTINATION ${CMAKE_CURRENT_BINARY_DIR}) # Add the executable. Remember to add all tests above this! add_executable(dGameTests ${DGAMETEST_SOURCES}) diff --git a/tests/dGameTests/GameDependencies.h b/tests/dGameTests/GameDependencies.h index 52e3919a..9f8dbb2b 100644 --- a/tests/dGameTests/GameDependencies.h +++ b/tests/dGameTests/GameDependencies.h @@ -8,6 +8,9 @@ #include "EntityInfo.h" #include "EntityManager.h" #include "dConfig.h" +#include "dZoneManager.h" +#include "GameDatabase/TestSQL/TestSQLDatabase.h" +#include "Database.h" #include class dZoneManager; @@ -20,6 +23,7 @@ public: ~dServerMock() {}; RakNet::BitStream* GetMostRecentBitStream() { return sentBitStream; }; void Send(RakNet::BitStream& bitStream, const SystemAddress& sysAddr, bool broadcast) override { sentBitStream = &bitStream; }; + void SetZoneId(unsigned int zoneId) { mZoneID = zoneId; } }; class GameDependenciesTest : public ::testing::Test { @@ -34,6 +38,9 @@ protected: Game::server = new dServerMock(); Game::config = new dConfig("worldconfig.ini"); Game::entityManager = new EntityManager(); + Game::zoneManager = new dZoneManager(); + Game::zoneManager->LoadZone(LWOZONEID(1, 0, 0)); + Database::_setDatabase(new TestSQLDatabase()); // this new is managed by the Database // Create a CDClientManager instance and load from defaults CDClientManager::LoadValuesFromDefaults(); @@ -42,6 +49,7 @@ protected: void TearDownDependencies() { if (Game::server) delete Game::server; if (Game::entityManager) delete Game::entityManager; + if (Game::zoneManager) delete Game::zoneManager; if (Game::logger) { Game::logger->Flush(); delete Game::logger; diff --git a/tests/dGameTests/dComponentsTests/CMakeLists.txt b/tests/dGameTests/dComponentsTests/CMakeLists.txt index 374095af..f73f1214 100644 --- a/tests/dGameTests/dComponentsTests/CMakeLists.txt +++ b/tests/dGameTests/dComponentsTests/CMakeLists.txt @@ -2,6 +2,7 @@ set(DCOMPONENTS_TESTS "DestroyableComponentTests.cpp" "PetComponentTests.cpp" "SimplePhysicsComponentTests.cpp" + "SavingTests.cpp" ) # Get the folder name and prepend it to the files above @@ -10,3 +11,8 @@ list(TRANSFORM DCOMPONENTS_TESTS PREPEND "${thisFolderName}/") # Export to parent scope set(DCOMPONENTS_TESTS ${DCOMPONENTS_TESTS} PARENT_SCOPE) + +# Copy test files to testing directory +add_subdirectory(TestData) +list(TRANSFORM COMPONENT_TEST_DATA PREPEND "${thisFolderName}/") +set(COMPONENT_TEST_DATA ${COMPONENT_TEST_DATA} PARENT_SCOPE) diff --git a/tests/dGameTests/dComponentsTests/SavingTests.cpp b/tests/dGameTests/dComponentsTests/SavingTests.cpp new file mode 100644 index 00000000..7123b698 --- /dev/null +++ b/tests/dGameTests/dComponentsTests/SavingTests.cpp @@ -0,0 +1,103 @@ +#include "GameDependencies.h" +#include "Character.h" +#include "Entity.h" +#include "tinyxml2.h" +#include "BuffComponent.h" +#include "CharacterComponent.h" + +class SavingTest : public GameDependenciesTest { +protected: + std::unique_ptr entity; + std::unique_ptr character; + tinyxml2::XMLDocument doc; + tinyxml2::XMLPrinter printer{ 0, true, 0 }; + + void SetUp() override { + SetUpDependencies(); + Game::zoneManager->LoadZone(LWOZONEID(1800, 2, 0)); + static_cast(Game::server)->SetZoneId(1800); + + entity = std::make_unique(1, GameDependenciesTest::info); + character = std::make_unique(1, nullptr); + + doc.LoadFile("./test_xml_data.xml"); + + entity->SetCharacter(character.get()); + character->SetEntity(entity.get()); + + doc.Print(&printer); + character->_setXmlData(printer.CStr()); + printer.ClearBuffer(); + + character->_doQuickXMLDataParse(); + character->LoadXmlRespawnCheckpoints(); + + entity->AddComponent(character.get(), UNASSIGNED_SYSTEM_ADDRESS)->LoadFromXml(entity->GetCharacter()->GetXMLDoc()); + } + + void TearDown() override { + entity->SetCharacter(nullptr); + + entity.reset(); + character.reset(); + + TearDownDependencies(); + } +}; + +TEST_F(SavingTest, CharacterComponentTest) { + // Print the original XML data + // character->GetXMLDoc().Print(&printer); + // std::string xmlDataOriginal(printer.CStr()); + // printer.ClearBuffer(); + // std::ofstream oldXml("./test_xml_data_original.xml"); + // oldXml << xmlDataOriginal; + + auto* characterComponent = entity->GetComponent(); + + // Update the xml document so its been run through the saver + character->SaveXMLToDatabase(); + + // Reload the component and character from the now updated xml data + const auto prevTotalTime = characterComponent->GetTotalTimePlayed(); + character->_doQuickXMLDataParse(); + entity->AddComponent(character.get(), UNASSIGNED_SYSTEM_ADDRESS); + characterComponent->LoadFromXml(entity->GetCharacter()->GetXMLDoc()); + + // Check that the buff component is the same as before which means resaving data and loading it back in didn't change anything + ASSERT_EQ("32114;69;343;13;163;2;181;2;388;252;146;24451;25;9022;41898;42186;42524;4404;0;0;0;0;0;0;0;0;0;", characterComponent->StatisticsToString()); + + // need a variable because the macros do not support {} + constexpr std::array correctCodes = { 1073741968, 0, 0, 0 }; + ASSERT_EQ(correctCodes, characterComponent->GetClaimCodes()); + ASSERT_EQ(1, characterComponent->m_Character->GetEyebrows()); + ASSERT_EQ(2, characterComponent->m_Character->GetEyes()); + ASSERT_EQ(9, characterComponent->m_Character->GetHairColor()); + ASSERT_EQ(8, characterComponent->m_Character->GetHairStyle()); + ASSERT_EQ(3, characterComponent->m_Character->GetPantsColor()); + ASSERT_EQ(27634704, characterComponent->m_Character->GetLeftHand()); + ASSERT_EQ(3, characterComponent->m_Character->GetMouth()); + ASSERT_EQ(27187396, characterComponent->m_Character->GetRightHand()); + ASSERT_EQ(13, characterComponent->m_Character->GetShirtColor()); + ASSERT_EQ(7510, characterComponent->GetUScore()); + ASSERT_EQ(300, characterComponent->GetReputation()); + ASSERT_EQ(u"0:1:4719+1:4720+1:4721", characterComponent->GetLastRocketConfig()); + ASSERT_EQ(prevTotalTime, characterComponent->GetTotalTimePlayed()); + + const std::map correctZoneStats = + { + { 1000, { .m_AchievementsCollected = 0, .m_BricksCollected = 0, .m_CoinsCollected = 4, .m_EnemiesSmashed = 0, .m_QuickBuildsCompleted = 0 } }, + { 1100, { .m_AchievementsCollected = 1, .m_BricksCollected = 54, .m_CoinsCollected = 584, .m_EnemiesSmashed = 34, .m_QuickBuildsCompleted = 0 } }, + { 1101, { .m_AchievementsCollected = 7, .m_BricksCollected = 0, .m_CoinsCollected = 750, .m_EnemiesSmashed = 100, .m_QuickBuildsCompleted = 7 } }, + { 1200, { .m_AchievementsCollected = 51, .m_BricksCollected = 9, .m_CoinsCollected = 26724, .m_EnemiesSmashed = 0, .m_QuickBuildsCompleted = 3 } }, + { 1250, { .m_AchievementsCollected = 1, .m_BricksCollected = 1, .m_CoinsCollected = 158, .m_EnemiesSmashed = 15, .m_QuickBuildsCompleted = 1 } }, + { 1800, { .m_AchievementsCollected = 4, .m_BricksCollected = 5, .m_CoinsCollected = 3894, .m_EnemiesSmashed = 14, .m_QuickBuildsCompleted = 2 } }, + }; + + ASSERT_EQ(correctZoneStats, characterComponent->GetZoneStatistics()); + + // Fails currently due to not reading style from xml + // Should the value be fixed, this test will fail and will match the above + // only then will this comment be removed. + ASSERT_NE(27, characterComponent->m_Character->GetShirtStyle()); +} diff --git a/tests/dGameTests/dComponentsTests/TestData/CMakeLists.txt b/tests/dGameTests/dComponentsTests/TestData/CMakeLists.txt new file mode 100644 index 00000000..31e92542 --- /dev/null +++ b/tests/dGameTests/dComponentsTests/TestData/CMakeLists.txt @@ -0,0 +1,10 @@ +set(COMPONENT_TEST_DATA + "test_xml_data.xml" +) + +# Get the folder name and prepend it to the files above +get_filename_component(thisFolderName ${CMAKE_CURRENT_SOURCE_DIR} NAME) +list(TRANSFORM COMPONENT_TEST_DATA PREPEND "${thisFolderName}/") + +# Export our list of files +set(COMPONENT_TEST_DATA ${COMPONENT_TEST_DATA} PARENT_SCOPE) diff --git a/tests/dGameTests/dComponentsTests/TestData/test_xml_data.xml b/tests/dGameTests/dComponentsTests/TestData/test_xml_data.xml new file mode 100644 index 00000000..431c12c9 --- /dev/null +++ b/tests/dGameTests/dComponentsTests/TestData/test_xml_data.xml @@ -0,0 +1 @@ +