diff --git a/apps/opencs_tests/CMakeLists.txt b/apps/opencs_tests/CMakeLists.txt index 00d8d0177c..92b14b797f 100644 --- a/apps/opencs_tests/CMakeLists.txt +++ b/apps/opencs_tests/CMakeLists.txt @@ -1,5 +1,6 @@ file(GLOB OPENCS_TESTS_SRC_FILES main.cpp + model/world/testinfocollection.cpp ) source_group(apps\\openmw-cs-tests FILES ${OPENCS_TESTS_SRC_FILES}) diff --git a/apps/opencs_tests/model/world/testinfocollection.cpp b/apps/opencs_tests/model/world/testinfocollection.cpp new file mode 100644 index 0000000000..9901266647 --- /dev/null +++ b/apps/opencs_tests/model/world/testinfocollection.cpp @@ -0,0 +1,122 @@ +#include "apps/opencs/model/world/infocollection.hpp" + +#include "components/esm3/esmreader.hpp" +#include "components/esm3/esmwriter.hpp" +#include "components/esm3/formatversion.hpp" +#include "components/esm3/loaddial.hpp" +#include "components/esm3/loadinfo.hpp" + +#include +#include + +#include +#include +#include + +namespace CSMWorld +{ + namespace + { + using namespace ::testing; + + std::unique_ptr saveDialogueWithInfos( + const ESM::Dialogue& dialogue, std::span infos) + { + auto stream = std::make_unique(); + + ESM::ESMWriter writer; + writer.setFormatVersion(ESM::CurrentSaveGameFormatVersion); + writer.save(*stream); + + writer.startRecord(ESM::REC_DIAL); + dialogue.save(writer); + writer.endRecord(ESM::REC_DIAL); + + for (const ESM::DialInfo& info : infos) + { + writer.startRecord(ESM::REC_INFO); + info.save(writer); + writer.endRecord(ESM::REC_INFO); + } + + return stream; + } + + void loadDialogueWithInfos(bool base, std::unique_ptr stream, InfoCollection& infoCollection, + InfosByTopic& infosByTopic) + { + ESM::ESMReader reader; + reader.open(std::move(stream), "test"); + + ASSERT_TRUE(reader.hasMoreRecs()); + ASSERT_EQ(reader.getRecName().toInt(), ESM::REC_DIAL); + reader.getRecHeader(); + bool isDeleted; + ESM::Dialogue dialogue; + dialogue.load(reader, isDeleted); + + while (reader.hasMoreRecs()) + { + ASSERT_EQ(reader.getRecName().toInt(), ESM::REC_INFO); + reader.getRecHeader(); + infoCollection.load(reader, base, dialogue, infosByTopic); + } + } + + void saveAndLoadDialogueWithInfos(const ESM::Dialogue& dialogue, std::span infos, + bool base, InfoCollection& infoCollection, InfosByTopic& infosByTopic) + { + loadDialogueWithInfos(base, saveDialogueWithInfos(dialogue, infos), infoCollection, infosByTopic); + } + + TEST(CSMWorldInfoCollectionTest, loadShouldAddRecord) + { + ESM::Dialogue dialogue; + dialogue.blank(); + dialogue.mId = ESM::RefId::stringRefId("dialogue1"); + + ESM::DialInfo info; + info.blank(); + info.mId = ESM::RefId::stringRefId("info1"); + + const bool base = true; + InfosByTopic infosByTopic; + InfoCollection collection; + saveAndLoadDialogueWithInfos(dialogue, std::array{ info }, base, collection, infosByTopic); + + EXPECT_EQ(collection.getSize(), 1); + ASSERT_EQ(collection.searchId(ESM::RefId::stringRefId("dialogue1#info1")), 0); + const Record& record = collection.getRecord(0); + ASSERT_EQ(record.mState, RecordBase::State_BaseOnly); + EXPECT_EQ(record.mBase.mTopicId, dialogue.mId); + EXPECT_EQ(record.mBase.mOriginalId, info.mId); + EXPECT_EQ(record.mBase.mId, ESM::RefId::stringRefId("dialogue1#info1")); + } + + TEST(CSMWorldInfoCollectionTest, loadShouldUpdateRecord) + { + ESM::Dialogue dialogue; + dialogue.blank(); + dialogue.mId = ESM::RefId::stringRefId("dialogue1"); + + ESM::DialInfo info; + info.blank(); + info.mId = ESM::RefId::stringRefId("info1"); + + const bool base = true; + InfosByTopic infosByTopic; + InfoCollection collection; + saveAndLoadDialogueWithInfos(dialogue, std::array{ info }, base, collection, infosByTopic); + + ESM::DialInfo updatedInfo = info; + updatedInfo.mActor = ESM::RefId::stringRefId("newActor"); + + saveAndLoadDialogueWithInfos(dialogue, std::array{ updatedInfo }, base, collection, infosByTopic); + + ASSERT_EQ(collection.searchId(ESM::RefId::stringRefId("dialogue1#info1")), 0); + const Record& record = collection.getRecord(0); + ASSERT_EQ(record.mState, RecordBase::State_BaseOnly); + EXPECT_EQ(record.mBase.mActor, ESM::RefId::stringRefId("newActor")); + } + } +}