1
0
mirror of https://gitlab.com/OpenMW/openmw.git synced 2025-02-04 03:40:14 +00:00
OpenMW/apps/openmw_test_suite/lua/test_configuration.cpp
fteppe 20da0892ef openMW_test_suite compiles and runs
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
2022-12-27 19:15:55 +01:00

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);
}
}
}