mirror of
https://gitlab.com/OpenMW/openmw.git
synced 2025-02-04 03:40:14 +00:00
20da0892ef
Slowly moving through the open-cs errors Good progress in openCS Very good progress on openCS Getting closer with openCS OpenCS compiles and runs! Didn't have time to test it all though ix openMW everything compiles on windows?? Fix gcc Fix Clang
253 lines
12 KiB
C++
253 lines
12 KiB
C++
#include "gmock/gmock.h"
|
|
#include <gtest/gtest.h>
|
|
|
|
#include <fstream>
|
|
|
|
#include <components/esm3/esmreader.hpp>
|
|
#include <components/esm3/esmwriter.hpp>
|
|
#include <components/esm3/readerscache.hpp>
|
|
#include <components/lua/configuration.hpp>
|
|
#include <components/lua/serialization.hpp>
|
|
|
|
#include "../testing_util.hpp"
|
|
|
|
namespace
|
|
{
|
|
|
|
using testing::ElementsAre;
|
|
using testing::Pair;
|
|
|
|
std::vector<std::pair<int, std::string>> asVector(const LuaUtil::ScriptIdsWithInitializationData& d)
|
|
{
|
|
std::vector<std::pair<int, std::string>> res;
|
|
for (const auto& [k, v] : d)
|
|
res.emplace_back(k, std::string(v));
|
|
return res;
|
|
}
|
|
|
|
TEST(LuaConfigurationTest, ValidOMWScripts)
|
|
{
|
|
ESM::LuaScriptsCfg cfg;
|
|
LuaUtil::parseOMWScripts(cfg, R"X(
|
|
# Lines starting with '#' are comments
|
|
GLOBAL: my_mod/#some_global_script.lua
|
|
|
|
# Script that will be automatically attached to the player
|
|
PLAYER :my_mod/player.lua
|
|
CUSTOM : my_mod/some_other_script.lua
|
|
NPC , CREATURE PLAYER : my_mod/some_other_script.lua)X");
|
|
LuaUtil::parseOMWScripts(cfg, ":my_mod/player.LUA \r\nCREATURE,CUSTOM: my_mod/creature.lua\r\n");
|
|
|
|
ASSERT_EQ(cfg.mScripts.size(), 6);
|
|
EXPECT_EQ(LuaUtil::scriptCfgToString(cfg.mScripts[0]), "GLOBAL : my_mod/#some_global_script.lua");
|
|
EXPECT_EQ(LuaUtil::scriptCfgToString(cfg.mScripts[1]), "PLAYER : my_mod/player.lua");
|
|
EXPECT_EQ(LuaUtil::scriptCfgToString(cfg.mScripts[2]), "CUSTOM : my_mod/some_other_script.lua");
|
|
EXPECT_EQ(LuaUtil::scriptCfgToString(cfg.mScripts[3]), "PLAYER NPC CREATURE : my_mod/some_other_script.lua");
|
|
EXPECT_EQ(LuaUtil::scriptCfgToString(cfg.mScripts[4]), ": my_mod/player.LUA");
|
|
EXPECT_EQ(LuaUtil::scriptCfgToString(cfg.mScripts[5]), "CUSTOM CREATURE : my_mod/creature.lua");
|
|
|
|
LuaUtil::ScriptsConfiguration conf;
|
|
conf.init(std::move(cfg));
|
|
ASSERT_EQ(conf.size(), 4);
|
|
EXPECT_EQ(LuaUtil::scriptCfgToString(conf[0]), "GLOBAL : my_mod/#some_global_script.lua");
|
|
// cfg.mScripts[1] is overridden by cfg.mScripts[4]
|
|
// cfg.mScripts[2] is overridden by cfg.mScripts[3]
|
|
EXPECT_EQ(LuaUtil::scriptCfgToString(conf[1]), "PLAYER NPC CREATURE : my_mod/some_other_script.lua");
|
|
EXPECT_EQ(LuaUtil::scriptCfgToString(conf[2]), ": my_mod/player.LUA");
|
|
EXPECT_EQ(LuaUtil::scriptCfgToString(conf[3]), "CUSTOM CREATURE : my_mod/creature.lua");
|
|
|
|
EXPECT_THAT(asVector(conf.getGlobalConf()), ElementsAre(Pair(0, "")));
|
|
EXPECT_THAT(asVector(conf.getPlayerConf()), ElementsAre(Pair(1, "")));
|
|
const ESM::RefId something = ESM::RefId::stringRefId("something");
|
|
|
|
EXPECT_THAT(asVector(conf.getLocalConf(ESM::REC_CONT, something, ESM::RefNum())), ElementsAre());
|
|
EXPECT_THAT(asVector(conf.getLocalConf(ESM::REC_NPC_, something, ESM::RefNum())), ElementsAre(Pair(1, "")));
|
|
EXPECT_THAT(asVector(conf.getLocalConf(ESM::REC_CREA, something, ESM::RefNum())),
|
|
ElementsAre(Pair(1, ""), Pair(3, "")));
|
|
|
|
// Check that initialization cleans old data
|
|
cfg = ESM::LuaScriptsCfg();
|
|
conf.init(std::move(cfg));
|
|
EXPECT_EQ(conf.size(), 0);
|
|
}
|
|
|
|
TEST(LuaConfigurationTest, InvalidOMWScripts)
|
|
{
|
|
ESM::LuaScriptsCfg cfg;
|
|
EXPECT_ERROR(LuaUtil::parseOMWScripts(cfg, "GLOBAL: something"),
|
|
"Lua script should have suffix '.lua', got: GLOBAL: something");
|
|
EXPECT_ERROR(LuaUtil::parseOMWScripts(cfg, "something.lua"), "No flags found in: something.lua");
|
|
|
|
cfg.mScripts.clear();
|
|
EXPECT_NO_THROW(LuaUtil::parseOMWScripts(cfg, "GLOBAL, PLAYER: something.lua"));
|
|
LuaUtil::ScriptsConfiguration conf;
|
|
EXPECT_ERROR(conf.init(std::move(cfg)), "Global script can not have local flags");
|
|
}
|
|
|
|
TEST(LuaConfigurationTest, ConfInit)
|
|
{
|
|
ESM::LuaScriptsCfg cfg;
|
|
ESM::LuaScriptCfg& script1 = cfg.mScripts.emplace_back();
|
|
script1.mScriptPath = "Script1.lua";
|
|
script1.mInitializationData = "data1";
|
|
script1.mFlags = ESM::LuaScriptCfg::sPlayer;
|
|
script1.mTypes.push_back(ESM::REC_CREA);
|
|
script1.mRecords.push_back({ true, ESM::RefId::stringRefId("record1"), "dataRecord1" });
|
|
script1.mRefs.push_back({ true, 2, 3, "" });
|
|
script1.mRefs.push_back({ true, 2, 4, "" });
|
|
|
|
ESM::LuaScriptCfg& script2 = cfg.mScripts.emplace_back();
|
|
script2.mScriptPath = "Script2.lua";
|
|
script2.mFlags = ESM::LuaScriptCfg::sCustom;
|
|
script2.mTypes.push_back(ESM::REC_CONT);
|
|
|
|
ESM::LuaScriptCfg& script1Extra = cfg.mScripts.emplace_back();
|
|
script1Extra.mScriptPath = "script1.LUA";
|
|
script1Extra.mFlags = ESM::LuaScriptCfg::sCustom | ESM::LuaScriptCfg::sMerge;
|
|
script1Extra.mTypes.push_back(ESM::REC_NPC_);
|
|
script1Extra.mRecords.push_back({ false, ESM::RefId::stringRefId("rat"), "" });
|
|
script1Extra.mRecords.push_back({ true, ESM::RefId::stringRefId("record2"), "" });
|
|
script1Extra.mRefs.push_back({ true, 3, 5, "dataRef35" });
|
|
script1Extra.mRefs.push_back({ false, 2, 3, "" });
|
|
|
|
LuaUtil::ScriptsConfiguration conf;
|
|
conf.init(cfg);
|
|
ASSERT_EQ(conf.size(), 2);
|
|
EXPECT_EQ(LuaUtil::scriptCfgToString(conf[0]),
|
|
"CUSTOM PLAYER CREATURE NPC : Script1.lua ; data 5 bytes ; 3 records ; 4 objects");
|
|
EXPECT_EQ(LuaUtil::scriptCfgToString(conf[1]), "CUSTOM CONTAINER : Script2.lua");
|
|
|
|
EXPECT_THAT(asVector(conf.getPlayerConf()), ElementsAre(Pair(0, "data1")));
|
|
EXPECT_THAT(asVector(conf.getLocalConf(ESM::REC_CONT, ESM::RefId::stringRefId("something"), ESM::RefNum())), ElementsAre(Pair(1, "")));
|
|
EXPECT_THAT(asVector(conf.getLocalConf(ESM::REC_CREA, ESM::RefId::stringRefId("guar"), ESM::RefNum())), ElementsAre(Pair(0, "data1")));
|
|
EXPECT_THAT(asVector(conf.getLocalConf(ESM::REC_CREA, ESM::RefId::stringRefId("rat"), ESM::RefNum())), ElementsAre());
|
|
EXPECT_THAT(
|
|
asVector(conf.getLocalConf(ESM::REC_DOOR, ESM::RefId::stringRefId("record1"), ESM::RefNum())), ElementsAre(Pair(0, "dataRecord1")));
|
|
EXPECT_THAT(
|
|
asVector(conf.getLocalConf(ESM::REC_DOOR, ESM::RefId::stringRefId("record2"), ESM::RefNum())), ElementsAre(Pair(0, "data1")));
|
|
EXPECT_THAT(asVector(conf.getLocalConf(ESM::REC_NPC_, ESM::RefId::stringRefId("record3"), { 1, 1 })), ElementsAre(Pair(0, "data1")));
|
|
EXPECT_THAT(asVector(conf.getLocalConf(ESM::REC_NPC_, ESM::RefId::stringRefId("record3"), { 2, 3 })), ElementsAre());
|
|
EXPECT_THAT(asVector(conf.getLocalConf(ESM::REC_NPC_, ESM::RefId::stringRefId("record3"), { 3, 5 })), ElementsAre(Pair(0, "dataRef35")));
|
|
EXPECT_THAT(asVector(conf.getLocalConf(ESM::REC_CONT, ESM::RefId::stringRefId("record4"), { 2, 4 })),
|
|
ElementsAre(Pair(0, "data1"), Pair(1, "")));
|
|
|
|
ESM::LuaScriptCfg& script3 = cfg.mScripts.emplace_back();
|
|
script3.mScriptPath = "script1.lua";
|
|
script3.mFlags = ESM::LuaScriptCfg::sGlobal;
|
|
EXPECT_ERROR(conf.init(cfg), "Flags mismatch for script1.lua");
|
|
}
|
|
|
|
TEST(LuaConfigurationTest, Serialization)
|
|
{
|
|
sol::state lua;
|
|
LuaUtil::BasicSerializer serializer;
|
|
|
|
ESM::ESMWriter writer;
|
|
writer.setAuthor("");
|
|
writer.setDescription("");
|
|
writer.setRecordCount(1);
|
|
writer.setFormat(ESM::Header::CurrentFormat);
|
|
writer.setVersion();
|
|
writer.addMaster("morrowind.esm", 0);
|
|
|
|
ESM::LuaScriptsCfg cfg;
|
|
std::string luaData;
|
|
{
|
|
sol::table data(lua, sol::create);
|
|
data["number"] = 5;
|
|
data["string"] = "some value";
|
|
data["fargoth"] = ESM::RefNum{ 128964, 1 };
|
|
luaData = LuaUtil::serialize(data, &serializer);
|
|
}
|
|
{
|
|
ESM::LuaScriptCfg& script = cfg.mScripts.emplace_back();
|
|
script.mScriptPath = "test_global.lua";
|
|
script.mFlags = ESM::LuaScriptCfg::sGlobal;
|
|
script.mInitializationData = luaData;
|
|
}
|
|
{
|
|
ESM::LuaScriptCfg& script = cfg.mScripts.emplace_back();
|
|
script.mScriptPath = "test_local.lua";
|
|
script.mFlags = ESM::LuaScriptCfg::sMerge;
|
|
script.mTypes.push_back(ESM::REC_DOOR);
|
|
script.mTypes.push_back(ESM::REC_MISC);
|
|
script.mRecords.push_back({ true, ESM::RefId::stringRefId("rat"), luaData });
|
|
script.mRecords.push_back({ false, ESM::RefId::stringRefId("chargendoorjournal"), "" });
|
|
script.mRefs.push_back({ true, 128964, 1, "" });
|
|
script.mRefs.push_back({ true, 128962, 1, luaData });
|
|
}
|
|
|
|
std::stringstream stream;
|
|
writer.save(stream);
|
|
writer.startRecord(ESM::REC_LUAL);
|
|
cfg.save(writer);
|
|
writer.endRecord(ESM::REC_LUAL);
|
|
writer.close();
|
|
std::string serializedOMWAddon = stream.str();
|
|
|
|
{
|
|
// Save for manual testing.
|
|
std::ofstream f(TestingOpenMW::outputFilePath("lua_conf_test.omwaddon"), std::ios::binary);
|
|
f << serializedOMWAddon;
|
|
f.close();
|
|
}
|
|
|
|
ESM::ESMReader reader;
|
|
reader.open(std::make_unique<std::istringstream>(serializedOMWAddon), "lua_conf_test.omwaddon");
|
|
ASSERT_EQ(reader.getRecordCount(), 1);
|
|
ASSERT_EQ(reader.getRecName().toInt(), ESM::REC_LUAL);
|
|
reader.getRecHeader();
|
|
ESM::LuaScriptsCfg loadedCfg;
|
|
loadedCfg.load(reader);
|
|
|
|
ASSERT_EQ(loadedCfg.mScripts.size(), cfg.mScripts.size());
|
|
for (size_t i = 0; i < cfg.mScripts.size(); ++i)
|
|
{
|
|
EXPECT_EQ(loadedCfg.mScripts[i].mScriptPath, cfg.mScripts[i].mScriptPath);
|
|
EXPECT_EQ(loadedCfg.mScripts[i].mFlags, cfg.mScripts[i].mFlags);
|
|
EXPECT_EQ(loadedCfg.mScripts[i].mInitializationData, cfg.mScripts[i].mInitializationData);
|
|
ASSERT_EQ(loadedCfg.mScripts[i].mTypes.size(), cfg.mScripts[i].mTypes.size());
|
|
for (size_t j = 0; j < cfg.mScripts[i].mTypes.size(); ++j)
|
|
EXPECT_EQ(loadedCfg.mScripts[i].mTypes[j], cfg.mScripts[i].mTypes[j]);
|
|
ASSERT_EQ(loadedCfg.mScripts[i].mRecords.size(), cfg.mScripts[i].mRecords.size());
|
|
for (size_t j = 0; j < cfg.mScripts[i].mRecords.size(); ++j)
|
|
{
|
|
EXPECT_EQ(loadedCfg.mScripts[i].mRecords[j].mAttach, cfg.mScripts[i].mRecords[j].mAttach);
|
|
EXPECT_EQ(loadedCfg.mScripts[i].mRecords[j].mRecordId, cfg.mScripts[i].mRecords[j].mRecordId);
|
|
EXPECT_EQ(loadedCfg.mScripts[i].mRecords[j].mInitializationData,
|
|
cfg.mScripts[i].mRecords[j].mInitializationData);
|
|
}
|
|
ASSERT_EQ(loadedCfg.mScripts[i].mRefs.size(), cfg.mScripts[i].mRefs.size());
|
|
for (size_t j = 0; j < cfg.mScripts[i].mRefs.size(); ++j)
|
|
{
|
|
EXPECT_EQ(loadedCfg.mScripts[i].mRefs[j].mAttach, cfg.mScripts[i].mRefs[j].mAttach);
|
|
EXPECT_EQ(loadedCfg.mScripts[i].mRefs[j].mRefnumIndex, cfg.mScripts[i].mRefs[j].mRefnumIndex);
|
|
EXPECT_EQ(
|
|
loadedCfg.mScripts[i].mRefs[j].mRefnumContentFile, cfg.mScripts[i].mRefs[j].mRefnumContentFile);
|
|
EXPECT_EQ(
|
|
loadedCfg.mScripts[i].mRefs[j].mInitializationData, cfg.mScripts[i].mRefs[j].mInitializationData);
|
|
}
|
|
}
|
|
|
|
{
|
|
ESM::ReadersCache readers(4);
|
|
readers.get(0)->openRaw(std::make_unique<std::istringstream>("dummyData"), "a.omwaddon");
|
|
readers.get(1)->openRaw(std::make_unique<std::istringstream>("dummyData"), "b.omwaddon");
|
|
readers.get(2)->openRaw(std::make_unique<std::istringstream>("dummyData"), "Morrowind.esm");
|
|
readers.get(3)->openRaw(std::make_unique<std::istringstream>("dummyData"), "c.omwaddon");
|
|
reader.setIndex(3);
|
|
reader.resolveParentFileIndices(readers);
|
|
}
|
|
loadedCfg.adjustRefNums(reader);
|
|
EXPECT_EQ(loadedCfg.mScripts[1].mRefs[0].mRefnumIndex, cfg.mScripts[1].mRefs[0].mRefnumIndex);
|
|
EXPECT_EQ(loadedCfg.mScripts[1].mRefs[0].mRefnumContentFile, 2);
|
|
{
|
|
sol::table data = LuaUtil::deserialize(
|
|
lua.lua_state(), loadedCfg.mScripts[1].mRefs[1].mInitializationData, &serializer);
|
|
ESM::RefNum adjustedRef = data["fargoth"].get<ESM::RefNum>();
|
|
EXPECT_EQ(adjustedRef.mIndex, 128964u);
|
|
EXPECT_EQ(adjustedRef.mContentFile, 2);
|
|
}
|
|
}
|
|
}
|