diff --git a/apps/components_tests/fx/technique.cpp b/apps/components_tests/fx/technique.cpp index 4a74ace7a8..ad57074b18 100644 --- a/apps/components_tests/fx/technique.cpp +++ b/apps/components_tests/fx/technique.cpp @@ -9,8 +9,9 @@ namespace { + constexpr VFS::Path::NormalizedView techniquePropertiesPath("shaders/technique_properties.omwfx"); - TestingOpenMW::VFSTestFile technique_properties(R"( + TestingOpenMW::VFSTestFile techniqueProperties(R"( fragment main {} vertex main {} technique { @@ -26,7 +27,9 @@ namespace } )"); - TestingOpenMW::VFSTestFile rendertarget_properties{ R"( + constexpr VFS::Path::NormalizedView rendertargetPropertiesPath("shaders/rendertarget_properties.omwfx"); + + TestingOpenMW::VFSTestFile rendertargetProperties{ R"( render_target rendertarget { width_ratio = 0.5; height_ratio = 0.5; @@ -52,7 +55,9 @@ namespace technique { passes = downsample2x, main; } )" }; - TestingOpenMW::VFSTestFile uniform_properties{ R"( + constexpr VFS::Path::NormalizedView uniformPropertiesPath("shaders/uniform_properties.omwfx"); + + TestingOpenMW::VFSTestFile uniformProperties{ R"( uniform_vec4 uVec4 { default = vec4(0,0,0,0); min = vec4(0,1,0,0); @@ -66,13 +71,17 @@ namespace technique { passes = main; } )" }; - TestingOpenMW::VFSTestFile missing_sampler_source{ R"( + constexpr VFS::Path::NormalizedView missingSamplerSourcePath("shaders/missing_sampler_source.omwfx"); + + TestingOpenMW::VFSTestFile missingSamplerSource{ R"( sampler_1d mysampler1d { } fragment main { } technique { passes = main; } )" }; - TestingOpenMW::VFSTestFile repeated_shared_block{ R"( + constexpr VFS::Path::NormalizedView repeatedSharedBlockPath("shaders/repeated_shared_block.omwfx"); + + TestingOpenMW::VFSTestFile repeatedSharedBlock{ R"( shared { float myfloat = 1.0; } @@ -92,11 +101,11 @@ namespace TechniqueTest() : mVFS(TestingOpenMW::createTestVFS({ - { "shaders/technique_properties.omwfx", &technique_properties }, - { "shaders/rendertarget_properties.omwfx", &rendertarget_properties }, - { "shaders/uniform_properties.omwfx", &uniform_properties }, - { "shaders/missing_sampler_source.omwfx", &missing_sampler_source }, - { "shaders/repeated_shared_block.omwfx", &repeated_shared_block }, + { techniquePropertiesPath, &techniqueProperties }, + { rendertargetPropertiesPath, &rendertargetProperties }, + { uniformPropertiesPath, &uniformProperties }, + { missingSamplerSourcePath, &missingSamplerSource }, + { repeatedSharedBlockPath, &repeatedSharedBlock }, })) , mImageManager(mVFS.get(), 0) { diff --git a/apps/components_tests/lua/test_configuration.cpp b/apps/components_tests/lua/test_configuration.cpp index 4d48927ecc..2cde0309d6 100644 --- a/apps/components_tests/lua/test_configuration.cpp +++ b/apps/components_tests/lua/test_configuration.cpp @@ -44,7 +44,7 @@ namespace 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[4]), ": my_mod/player.lua"); EXPECT_EQ(LuaUtil::scriptCfgToString(cfg.mScripts[5]), "CUSTOM CREATURE : my_mod/creature.lua"); LuaUtil::ScriptsConfiguration conf; @@ -54,7 +54,7 @@ namespace // 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[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, ""))); @@ -89,7 +89,7 @@ namespace { ESM::LuaScriptsCfg cfg; ESM::LuaScriptCfg& script1 = cfg.mScripts.emplace_back(); - script1.mScriptPath = "Script1.lua"; + script1.mScriptPath = VFS::Path::Normalized("Script1.lua"); script1.mInitializationData = "data1"; script1.mFlags = ESM::LuaScriptCfg::sPlayer; script1.mTypes.push_back(ESM::REC_CREA); @@ -98,12 +98,12 @@ namespace script1.mRefs.push_back({ true, 2, 4, "" }); ESM::LuaScriptCfg& script2 = cfg.mScripts.emplace_back(); - script2.mScriptPath = "Script2.lua"; + script2.mScriptPath = VFS::Path::Normalized("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.mScriptPath = VFS::Path::Normalized("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"), "" }); @@ -115,8 +115,8 @@ namespace 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"); + "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())), @@ -139,7 +139,7 @@ namespace ElementsAre(Pair(0, "data1"), Pair(1, ""))); ESM::LuaScriptCfg& script3 = cfg.mScripts.emplace_back(); - script3.mScriptPath = "script1.lua"; + script3.mScriptPath = VFS::Path::Normalized("script1.lua"); script3.mFlags = ESM::LuaScriptCfg::sGlobal; EXPECT_ERROR(conf.init(cfg), "Flags mismatch for script1.lua"); } @@ -168,13 +168,13 @@ namespace } { ESM::LuaScriptCfg& script = cfg.mScripts.emplace_back(); - script.mScriptPath = "test_global.lua"; + script.mScriptPath = VFS::Path::Normalized("test_global.lua"); script.mFlags = ESM::LuaScriptCfg::sGlobal; script.mInitializationData = luaData; } { ESM::LuaScriptCfg& script = cfg.mScripts.emplace_back(); - script.mScriptPath = "test_local.lua"; + script.mScriptPath = VFS::Path::Normalized("test_local.lua"); script.mFlags = ESM::LuaScriptCfg::sMerge; script.mTypes.push_back(ESM::REC_DOOR); script.mTypes.push_back(ESM::REC_MISC); diff --git a/apps/components_tests/lua/test_l10n.cpp b/apps/components_tests/lua/test_l10n.cpp index d58bd41a94..b48028a730 100644 --- a/apps/components_tests/lua/test_l10n.cpp +++ b/apps/components_tests/lua/test_l10n.cpp @@ -18,6 +18,13 @@ namespace return lua.safe_script("return " + luaCode).get(); } + constexpr VFS::Path::NormalizedView test1EnPath("l10n/test1/en.yaml"); + constexpr VFS::Path::NormalizedView test1EnUsPath("l10n/test1/en_us.yaml"); + constexpr VFS::Path::NormalizedView test1DePath("l10n/test1/de.yaml"); + constexpr VFS::Path::NormalizedView test2EnPath("l10n/test2/en.yaml"); + constexpr VFS::Path::NormalizedView test3EnPath("l10n/test3/en.yaml"); + constexpr VFS::Path::NormalizedView test3DePath("l10n/test3/de.yaml"); + VFSTestFile invalidScript("not a script"); VFSTestFile incorrectScript( "return { incorrectSection = {}, engineHandlers = { incorrectHandler = function() end } }"); @@ -67,12 +74,12 @@ you_have_arrows: "Arrows count: {count}" struct LuaL10nTest : Test { std::unique_ptr mVFS = createTestVFS({ - { "l10n/Test1/en.yaml", &test1En }, - { "l10n/Test1/en_US.yaml", &test1EnUS }, - { "l10n/Test1/de.yaml", &test1De }, - { "l10n/Test2/en.yaml", &test2En }, - { "l10n/Test3/en.yaml", &test1En }, - { "l10n/Test3/de.yaml", &test1De }, + { test1EnPath, &test1En }, + { test1EnUsPath, &test1EnUS }, + { test1DePath, &test1De }, + { test2EnPath, &test2En }, + { test3EnPath, &test1En }, + { test3DePath, &test1De }, }); LuaUtil::ScriptsConfiguration mCfg; diff --git a/apps/components_tests/lua/test_lua.cpp b/apps/components_tests/lua/test_lua.cpp index a4b78889bb..5f1e11c435 100644 --- a/apps/components_tests/lua/test_lua.cpp +++ b/apps/components_tests/lua/test_lua.cpp @@ -9,6 +9,8 @@ namespace { using namespace testing; + constexpr VFS::Path::NormalizedView counterPath("aaa/counter.lua"); + TestingOpenMW::VFSTestFile counterFile(R"X( x = 42 return { @@ -17,8 +19,12 @@ return { } )X"); + constexpr VFS::Path::NormalizedView invalidPath("invalid.lua"); + TestingOpenMW::VFSTestFile invalidScriptFile("Invalid script"); + constexpr VFS::Path::NormalizedView testsPath("bbb/tests.lua"); + TestingOpenMW::VFSTestFile testsFile(R"X( return { -- should work @@ -51,6 +57,8 @@ return { } )X"); + constexpr VFS::Path::NormalizedView metaIndexErrorPath("metaindexerror.lua"); + TestingOpenMW::VFSTestFile metaIndexErrorFile( "return setmetatable({}, { __index = function(t, key) error('meta index error') end })"); @@ -66,14 +74,24 @@ return { return buf.str(); } + constexpr VFS::Path::NormalizedView bigPath("big.lua"); + TestingOpenMW::VFSTestFile bigScriptFile(genBigScript()); + + constexpr VFS::Path::NormalizedView requireBigPath("requirebig.lua"); + TestingOpenMW::VFSTestFile requireBigScriptFile("local x = require('big') ; return {x}"); struct LuaStateTest : Test { - std::unique_ptr mVFS = TestingOpenMW::createTestVFS({ { "aaa/counter.lua", &counterFile }, - { "bbb/tests.lua", &testsFile }, { "invalid.lua", &invalidScriptFile }, { "big.lua", &bigScriptFile }, - { "requireBig.lua", &requireBigScriptFile }, { "metaIndexError.lua", &metaIndexErrorFile } }); + std::unique_ptr mVFS = TestingOpenMW::createTestVFS({ + { counterPath, &counterFile }, + { testsPath, &testsFile }, + { invalidPath, &invalidScriptFile }, + { bigPath, &bigScriptFile }, + { requireBigPath, &requireBigScriptFile }, + { metaIndexErrorPath, &metaIndexErrorFile }, + }); LuaUtil::ScriptsConfiguration mCfg; LuaUtil::LuaState mLua{ mVFS.get(), &mCfg }; @@ -81,7 +99,7 @@ return { TEST_F(LuaStateTest, Sandbox) { - const VFS::Path::Normalized path("aaa/counter.lua"); + const VFS::Path::Normalized path(counterPath); sol::table script1 = mLua.runInNewSandbox(path); EXPECT_EQ(LuaUtil::call(script1["get"]).get(), 42); diff --git a/apps/components_tests/lua/test_scriptscontainer.cpp b/apps/components_tests/lua/test_scriptscontainer.cpp index 7491675a01..b4f08e9ab6 100644 --- a/apps/components_tests/lua/test_scriptscontainer.cpp +++ b/apps/components_tests/lua/test_scriptscontainer.cpp @@ -14,11 +14,22 @@ namespace using namespace testing; using namespace TestingOpenMW; + constexpr VFS::Path::NormalizedView invalidPath("invalid.lua"); + VFSTestFile invalidScript("not a script"); + + constexpr VFS::Path::NormalizedView incorrectPath("incorrect.lua"); + VFSTestFile incorrectScript( "return { incorrectSection = {}, engineHandlers = { incorrectHandler = function() end } }"); + + constexpr VFS::Path::NormalizedView emptyPath("empty.lua"); + VFSTestFile emptyScript(""); + constexpr VFS::Path::NormalizedView test1Path("test1.lua"); + constexpr VFS::Path::NormalizedView test2Path("test2.lua"); + VFSTestFile testScript(R"X( return { engineHandlers = { @@ -33,6 +44,8 @@ return { } )X"); + constexpr VFS::Path::NormalizedView stopEventPath("stopevent.lua"); + VFSTestFile stopEventScript(R"X( return { eventHandlers = { @@ -44,6 +57,9 @@ return { } )X"); + constexpr VFS::Path::NormalizedView loadSave1Path("loadsave1.lua"); + constexpr VFS::Path::NormalizedView loadSave2Path("loadsave2.lua"); + VFSTestFile loadSaveScript(R"X( x = 0 y = 0 @@ -70,6 +86,8 @@ return { } )X"); + constexpr VFS::Path::NormalizedView testInterfacePath("testinterface.lua"); + VFSTestFile interfaceScript(R"X( return { interfaceName = "TestInterface", @@ -80,6 +98,8 @@ return { } )X"); + constexpr VFS::Path::NormalizedView overrideInterfacePath("overrideinterface.lua"); + VFSTestFile overrideInterfaceScript(R"X( local old = nil local interface = { @@ -104,6 +124,8 @@ return { } )X"); + constexpr VFS::Path::NormalizedView useInterfacePath("useinterface.lua"); + VFSTestFile useInterfaceScript(R"X( local interfaces = require('openmw.interfaces') return { @@ -118,17 +140,17 @@ return { struct LuaScriptsContainerTest : Test { std::unique_ptr mVFS = createTestVFS({ - { "invalid.lua", &invalidScript }, - { "incorrect.lua", &incorrectScript }, - { "empty.lua", &emptyScript }, - { "test1.lua", &testScript }, - { "test2.lua", &testScript }, - { "stopEvent.lua", &stopEventScript }, - { "loadSave1.lua", &loadSaveScript }, - { "loadSave2.lua", &loadSaveScript }, - { "testInterface.lua", &interfaceScript }, - { "overrideInterface.lua", &overrideInterfaceScript }, - { "useInterface.lua", &useInterfaceScript }, + { invalidPath, &invalidScript }, + { incorrectPath, &incorrectScript }, + { emptyPath, &emptyScript }, + { test1Path, &testScript }, + { test2Path, &testScript }, + { stopEventPath, &stopEventScript }, + { loadSave1Path, &loadSaveScript }, + { loadSave2Path, &loadSaveScript }, + { testInterfacePath, &interfaceScript }, + { overrideInterfacePath, &overrideInterfaceScript }, + { useInterfacePath, &useInterfaceScript }, }); LuaUtil::ScriptsConfiguration mCfg; @@ -152,39 +174,49 @@ CUSTOM, PLAYER: useInterface.lua )X"); mCfg.init(std::move(cfg)); } + + int getId(VFS::Path::NormalizedView path) const + { + const std::optional id = mCfg.findId(path); + if (!id.has_value()) + throw std::invalid_argument("Script id is not found: " + std::string(path.value())); + return *id; + } }; - TEST_F(LuaScriptsContainerTest, VerifyStructure) + TEST_F(LuaScriptsContainerTest, addCustomScriptShouldNotStartInvalidScript) { LuaUtil::ScriptsContainer scripts(&mLua, "Test"); - { - testing::internal::CaptureStdout(); - EXPECT_FALSE(scripts.addCustomScript(*mCfg.findId("invalid.lua"))); - std::string output = testing::internal::GetCapturedStdout(); - EXPECT_THAT(output, HasSubstr("Can't start Test[invalid.lua]")); - } - { - testing::internal::CaptureStdout(); - EXPECT_TRUE(scripts.addCustomScript(*mCfg.findId("incorrect.lua"))); - std::string output = testing::internal::GetCapturedStdout(); - EXPECT_THAT(output, HasSubstr("Not supported handler 'incorrectHandler' in Test[incorrect.lua]")); - EXPECT_THAT(output, HasSubstr("Not supported section 'incorrectSection' in Test[incorrect.lua]")); - } - { - testing::internal::CaptureStdout(); - EXPECT_TRUE(scripts.addCustomScript(*mCfg.findId("empty.lua"))); - EXPECT_FALSE(scripts.addCustomScript(*mCfg.findId("empty.lua"))); // already present - EXPECT_EQ(internal::GetCapturedStdout(), ""); - } + testing::internal::CaptureStdout(); + EXPECT_FALSE(scripts.addCustomScript(getId(invalidPath))); + std::string output = testing::internal::GetCapturedStdout(); + EXPECT_THAT(output, HasSubstr("Can't start Test[invalid.lua]")); + } + + TEST_F(LuaScriptsContainerTest, addCustomScriptShouldNotSuportScriptsWithInvalidHandlerAndSection) + { + LuaUtil::ScriptsContainer scripts(&mLua, "Test"); + testing::internal::CaptureStdout(); + EXPECT_TRUE(scripts.addCustomScript(getId(incorrectPath))); + std::string output = testing::internal::GetCapturedStdout(); + EXPECT_THAT(output, HasSubstr("Not supported handler 'incorrectHandler' in Test[incorrect.lua]")); + EXPECT_THAT(output, HasSubstr("Not supported section 'incorrectSection' in Test[incorrect.lua]")); + } + + TEST_F(LuaScriptsContainerTest, addCustomScriptShouldReturnFalseForDuplicates) + { + LuaUtil::ScriptsContainer scripts(&mLua, "Test"); + EXPECT_TRUE(scripts.addCustomScript(getId(emptyPath))); + EXPECT_FALSE(scripts.addCustomScript(getId(emptyPath))); } TEST_F(LuaScriptsContainerTest, CallHandler) { LuaUtil::ScriptsContainer scripts(&mLua, "Test"); testing::internal::CaptureStdout(); - EXPECT_TRUE(scripts.addCustomScript(*mCfg.findId("test1.lua"))); - EXPECT_TRUE(scripts.addCustomScript(*mCfg.findId("stopEvent.lua"))); - EXPECT_TRUE(scripts.addCustomScript(*mCfg.findId("test2.lua"))); + EXPECT_TRUE(scripts.addCustomScript(getId(test1Path))); + EXPECT_TRUE(scripts.addCustomScript(getId(stopEventPath))); + EXPECT_TRUE(scripts.addCustomScript(getId(test2Path))); scripts.update(1.5f); EXPECT_EQ(internal::GetCapturedStdout(), "Test[test1.lua]:\t update 1.5\n" @@ -194,9 +226,10 @@ CUSTOM, PLAYER: useInterface.lua TEST_F(LuaScriptsContainerTest, CallEvent) { LuaUtil::ScriptsContainer scripts(&mLua, "Test"); - EXPECT_TRUE(scripts.addCustomScript(*mCfg.findId("test1.lua"))); - EXPECT_TRUE(scripts.addCustomScript(*mCfg.findId("stopEvent.lua"))); - EXPECT_TRUE(scripts.addCustomScript(*mCfg.findId("test2.lua"))); + + EXPECT_TRUE(scripts.addCustomScript(getId(test1Path))); + EXPECT_TRUE(scripts.addCustomScript(getId(stopEventPath))); + EXPECT_TRUE(scripts.addCustomScript(getId(test2Path))); sol::state_view sol = mLua.unsafeState(); std::string X0 = LuaUtil::serialize(sol.create_table_with("x", 0.5)); @@ -212,7 +245,7 @@ CUSTOM, PLAYER: useInterface.lua scripts.receiveEvent("Event1", X1); EXPECT_EQ(internal::GetCapturedStdout(), "Test[test2.lua]:\t event1 1.5\n" - "Test[stopEvent.lua]:\t event1 1.5\n" + "Test[stopevent.lua]:\t event1 1.5\n" "Test[test1.lua]:\t event1 1.5\n"); } { @@ -227,7 +260,7 @@ CUSTOM, PLAYER: useInterface.lua scripts.receiveEvent("Event1", X0); EXPECT_EQ(internal::GetCapturedStdout(), "Test[test2.lua]:\t event1 0.5\n" - "Test[stopEvent.lua]:\t event1 0.5\n"); + "Test[stopevent.lua]:\t event1 0.5\n"); } { testing::internal::CaptureStdout(); @@ -241,9 +274,11 @@ CUSTOM, PLAYER: useInterface.lua TEST_F(LuaScriptsContainerTest, RemoveScript) { LuaUtil::ScriptsContainer scripts(&mLua, "Test"); - EXPECT_TRUE(scripts.addCustomScript(*mCfg.findId("test1.lua"))); - EXPECT_TRUE(scripts.addCustomScript(*mCfg.findId("stopEvent.lua"))); - EXPECT_TRUE(scripts.addCustomScript(*mCfg.findId("test2.lua"))); + + EXPECT_TRUE(scripts.addCustomScript(getId(test1Path))); + EXPECT_TRUE(scripts.addCustomScript(getId(stopEventPath))); + EXPECT_TRUE(scripts.addCustomScript(getId(test2Path))); + sol::state_view sol = mLua.unsafeState(); std::string X = LuaUtil::serialize(sol.create_table_with("x", 0.5)); @@ -255,11 +290,11 @@ CUSTOM, PLAYER: useInterface.lua "Test[test1.lua]:\t update 1.5\n" "Test[test2.lua]:\t update 1.5\n" "Test[test2.lua]:\t event1 0.5\n" - "Test[stopEvent.lua]:\t event1 0.5\n"); + "Test[stopevent.lua]:\t event1 0.5\n"); } { testing::internal::CaptureStdout(); - int stopEventScriptId = *mCfg.findId("stopEvent.lua"); + const int stopEventScriptId = getId(stopEventPath); EXPECT_TRUE(scripts.hasScript(stopEventScriptId)); scripts.removeScript(stopEventScriptId); EXPECT_FALSE(scripts.hasScript(stopEventScriptId)); @@ -273,7 +308,7 @@ CUSTOM, PLAYER: useInterface.lua } { testing::internal::CaptureStdout(); - scripts.removeScript(*mCfg.findId("test1.lua")); + scripts.removeScript(getId(test1Path)); scripts.update(1.5f); scripts.receiveEvent("Event1", X); EXPECT_EQ(internal::GetCapturedStdout(), @@ -290,19 +325,19 @@ CUSTOM, PLAYER: useInterface.lua scripts.addAutoStartedScripts(); scripts.update(1.5f); EXPECT_EQ(internal::GetCapturedStdout(), - "Test[overrideInterface.lua]:\toverride\n" - "Test[overrideInterface.lua]:\tinit\n" - "Test[overrideInterface.lua]:\tNEW FN\t4.5\n" - "Test[testInterface.lua]:\tFN\t4.5\n"); + "Test[overrideinterface.lua]:\toverride\n" + "Test[overrideinterface.lua]:\tinit\n" + "Test[overrideinterface.lua]:\tNEW FN\t4.5\n" + "Test[testinterface.lua]:\tFN\t4.5\n"); } TEST_F(LuaScriptsContainerTest, Interface) { LuaUtil::ScriptsContainer scripts(&mLua, "Test"); scripts.setAutoStartConf(mCfg.getLocalConf(ESM::REC_CREA, ESM::RefId(), ESM::RefNum())); - int addIfaceId = *mCfg.findId("testInterface.lua"); - int overrideIfaceId = *mCfg.findId("overrideInterface.lua"); - int useIfaceId = *mCfg.findId("useInterface.lua"); + const int addIfaceId = getId(testInterfacePath); + const int overrideIfaceId = getId(overrideInterfacePath); + const int useIfaceId = getId(useInterfacePath); testing::internal::CaptureStdout(); scripts.addAutoStartedScripts(); @@ -317,11 +352,11 @@ CUSTOM, PLAYER: useInterface.lua scripts.removeScript(overrideIfaceId); scripts.update(1.5f); EXPECT_EQ(internal::GetCapturedStdout(), - "Test[overrideInterface.lua]:\toverride\n" - "Test[overrideInterface.lua]:\tinit\n" - "Test[overrideInterface.lua]:\tNEW FN\t4.5\n" - "Test[testInterface.lua]:\tFN\t4.5\n" - "Test[testInterface.lua]:\tFN\t3.5\n"); + "Test[overrideinterface.lua]:\toverride\n" + "Test[overrideinterface.lua]:\tinit\n" + "Test[overrideinterface.lua]:\tNEW FN\t4.5\n" + "Test[testinterface.lua]:\tFN\t4.5\n" + "Test[testinterface.lua]:\tFN\t3.5\n"); } TEST_F(LuaScriptsContainerTest, LoadSave) @@ -334,7 +369,7 @@ CUSTOM, PLAYER: useInterface.lua scripts3.setAutoStartConf(mCfg.getPlayerConf()); scripts1.addAutoStartedScripts(); - EXPECT_TRUE(scripts1.addCustomScript(*mCfg.findId("test1.lua"))); + EXPECT_TRUE(scripts1.addCustomScript(getId(test1Path))); sol::state_view sol = mLua.unsafeState(); scripts1.receiveEvent("Set", LuaUtil::serialize(sol.create_table_with("n", 1, "x", 0.5, "y", 3.5))); @@ -349,23 +384,23 @@ CUSTOM, PLAYER: useInterface.lua scripts2.receiveEvent("Print", ""); EXPECT_EQ(internal::GetCapturedStdout(), "Test[test1.lua]:\tload\n" - "Test[loadSave2.lua]:\t0.5\t3.5\n" - "Test[loadSave1.lua]:\t2.5\t1.5\n" + "Test[loadsave2.lua]:\t0.5\t3.5\n" + "Test[loadsave1.lua]:\t2.5\t1.5\n" "Test[test1.lua]:\tprint\n"); - EXPECT_FALSE(scripts2.hasScript(*mCfg.findId("testInterface.lua"))); + EXPECT_FALSE(scripts2.hasScript(getId(testInterfacePath))); } { testing::internal::CaptureStdout(); scripts3.load(data); scripts3.receiveEvent("Print", ""); EXPECT_EQ(internal::GetCapturedStdout(), - "Ignoring Test[loadSave1.lua]; this script is not allowed here\n" + "Ignoring Test[loadsave1.lua]; this script is not allowed here\n" "Test[test1.lua]:\tload\n" - "Test[overrideInterface.lua]:\toverride\n" - "Test[overrideInterface.lua]:\tinit\n" - "Test[loadSave2.lua]:\t0.5\t3.5\n" + "Test[overrideinterface.lua]:\toverride\n" + "Test[overrideinterface.lua]:\tinit\n" + "Test[loadsave2.lua]:\t0.5\t3.5\n" "Test[test1.lua]:\tprint\n"); - EXPECT_TRUE(scripts3.hasScript(*mCfg.findId("testInterface.lua"))); + EXPECT_TRUE(scripts3.hasScript(getId(testInterfacePath))); } } @@ -373,8 +408,8 @@ CUSTOM, PLAYER: useInterface.lua { using TimerType = LuaUtil::ScriptsContainer::TimerType; LuaUtil::ScriptsContainer scripts(&mLua, "Test"); - int test1Id = *mCfg.findId("test1.lua"); - int test2Id = *mCfg.findId("test2.lua"); + const int test1Id = getId(test1Path); + const int test2Id = getId(test2Path); testing::internal::CaptureStdout(); EXPECT_TRUE(scripts.addCustomScript(test1Id)); diff --git a/apps/components_tests/misc/test_resourcehelpers.cpp b/apps/components_tests/misc/test_resourcehelpers.cpp index 964442e735..05079ae875 100644 --- a/apps/components_tests/misc/test_resourcehelpers.cpp +++ b/apps/components_tests/misc/test_resourcehelpers.cpp @@ -8,16 +8,17 @@ namespace using namespace Misc::ResourceHelpers; TEST(CorrectSoundPath, wav_files_not_overridden_with_mp3_in_vfs_are_not_corrected) { - std::unique_ptr mVFS = TestingOpenMW::createTestVFS({ { "sound/bar.wav", nullptr } }); constexpr VFS::Path::NormalizedView path("sound/bar.wav"); + std::unique_ptr mVFS = TestingOpenMW::createTestVFS({ { path, nullptr } }); EXPECT_EQ(correctSoundPath(path, *mVFS), "sound/bar.wav"); } TEST(CorrectSoundPath, wav_files_overridden_with_mp3_in_vfs_are_corrected) { - std::unique_ptr mVFS = TestingOpenMW::createTestVFS({ { "sound/foo.mp3", nullptr } }); - constexpr VFS::Path::NormalizedView path("sound/foo.wav"); - EXPECT_EQ(correctSoundPath(path, *mVFS), "sound/foo.mp3"); + constexpr VFS::Path::NormalizedView mp3("sound/foo.mp3"); + std::unique_ptr mVFS = TestingOpenMW::createTestVFS({ { mp3, nullptr } }); + constexpr VFS::Path::NormalizedView wav("sound/foo.wav"); + EXPECT_EQ(correctSoundPath(wav, *mVFS), "sound/foo.mp3"); } TEST(CorrectSoundPath, corrected_path_does_not_check_existence_in_vfs) diff --git a/apps/openmw/mwlua/luamanagerimp.cpp b/apps/openmw/mwlua/luamanagerimp.cpp index 658652f793..cf55ac63e6 100644 --- a/apps/openmw/mwlua/luamanagerimp.cpp +++ b/apps/openmw/mwlua/luamanagerimp.cpp @@ -850,8 +850,8 @@ namespace MWLua bool isMenu = mConfiguration[i].mFlags & ESM::LuaScriptCfg::sMenu; out << std::left; - out << " " << std::setw(nameW) << mConfiguration[i].mScriptPath; - if (mConfiguration[i].mScriptPath.size() > nameW) + out << " " << std::setw(nameW) << mConfiguration[i].mScriptPath.value(); + if (mConfiguration[i].mScriptPath.value().size() > nameW) out << "\n " << std::setw(nameW) << ""; // if path is too long, break line out << std::right; out << std::setw(valueW) << static_cast(activeStats[i].mAvgInstructionCount); diff --git a/apps/openmw/mwlua/objectbindings.cpp b/apps/openmw/mwlua/objectbindings.cpp index 3cd68363fb..6575a719f6 100644 --- a/apps/openmw/mwlua/objectbindings.cpp +++ b/apps/openmw/mwlua/objectbindings.cpp @@ -390,7 +390,7 @@ namespace MWLua }; objectT["addScript"] = [context](const GObject& object, std::string_view path, sol::object initData) { const LuaUtil::ScriptsConfiguration& cfg = context.mLua->getConfiguration(); - std::optional scriptId = cfg.findId(path); + std::optional scriptId = cfg.findId(VFS::Path::Normalized(path)); if (!scriptId) throw std::runtime_error("Unknown script: " + std::string(path)); if (!(cfg[*scriptId].mFlags & ESM::LuaScriptCfg::sCustom)) @@ -407,7 +407,7 @@ namespace MWLua }; objectT["hasScript"] = [lua = context.mLua](const GObject& object, std::string_view path) { const LuaUtil::ScriptsConfiguration& cfg = lua->getConfiguration(); - std::optional scriptId = cfg.findId(path); + std::optional scriptId = cfg.findId(VFS::Path::Normalized(path)); if (!scriptId) return false; MWWorld::Ptr ptr = object.ptr(); @@ -419,7 +419,7 @@ namespace MWLua }; objectT["removeScript"] = [lua = context.mLua](const GObject& object, std::string_view path) { const LuaUtil::ScriptsConfiguration& cfg = lua->getConfiguration(); - std::optional scriptId = cfg.findId(path); + std::optional scriptId = cfg.findId(VFS::Path::Normalized(path)); if (!scriptId) throw std::runtime_error("Unknown script: " + std::string(path)); MWWorld::Ptr ptr = object.ptr(); diff --git a/components/esm/luascripts.hpp b/components/esm/luascripts.hpp index 01d322285f..705e3f106c 100644 --- a/components/esm/luascripts.hpp +++ b/components/esm/luascripts.hpp @@ -2,6 +2,8 @@ #define OPENMW_ESM_LUASCRIPTS_H #include +#include + #include #include #include @@ -25,7 +27,7 @@ namespace ESM static constexpr Flags sMenu = 1ull << 4; // start as a menu script - std::string mScriptPath; // VFS path to the script. + VFS::Path::Normalized mScriptPath; std::string mInitializationData; // Serialized Lua table. It is a binary data. Can contain '\0'. Flags mFlags; // bitwise OR of Flags. @@ -85,7 +87,7 @@ namespace ESM struct LuaScript { - std::string mScriptPath; + VFS::Path::Normalized mScriptPath; std::string mData; // Serialized Lua table. It is a binary data. Can contain '\0'. std::vector mTimers; }; diff --git a/components/lua/configuration.cpp b/components/lua/configuration.cpp index c6c296f8d5..b327270fc1 100644 --- a/components/lua/configuration.cpp +++ b/components/lua/configuration.cpp @@ -60,16 +60,17 @@ namespace LuaUtil const ESM::LuaScriptCfg& script = cfg.mScripts[i]; bool global = script.mFlags & ESM::LuaScriptCfg::sGlobal; if (global && (script.mFlags & ~ESM::LuaScriptCfg::sMerge) != ESM::LuaScriptCfg::sGlobal) - throw std::runtime_error(std::string("Global script can not have local flags: ") + script.mScriptPath); + throw std::runtime_error( + std::string("Global script can not have local flags: ") + script.mScriptPath.value()); if (global && (!script.mTypes.empty() || !script.mRecords.empty() || !script.mRefs.empty())) throw std::runtime_error(std::string("Global script can not have per-type and per-object configuration") - + script.mScriptPath); - auto [it, inserted] = mPathToIndex.emplace(Misc::StringUtils::lowerCase(script.mScriptPath), i); + + script.mScriptPath.value()); + auto [it, inserted] = mPathToIndex.emplace(script.mScriptPath, i); if (inserted) continue; ESM::LuaScriptCfg& oldScript = cfg.mScripts[it->second]; if (global != bool(oldScript.mFlags & ESM::LuaScriptCfg::sGlobal)) - throw std::runtime_error(std::string("Flags mismatch for ") + script.mScriptPath); + throw std::runtime_error(std::string("Flags mismatch for ") + script.mScriptPath.value()); if (script.mFlags & ESM::LuaScriptCfg::sMerge) { oldScript.mFlags |= (script.mFlags & ~ESM::LuaScriptCfg::sMerge); @@ -113,7 +114,7 @@ namespace LuaUtil } } - std::optional ScriptsConfiguration::findId(std::string_view path) const + std::optional ScriptsConfiguration::findId(VFS::Path::NormalizedView path) const { auto it = mPathToIndex.find(path); if (it != mPathToIndex.end()) @@ -199,7 +200,7 @@ namespace LuaUtil scriptPath = scriptPath.substr(1); ESM::LuaScriptCfg& script = cfg.mScripts.emplace_back(); - script.mScriptPath = std::string(scriptPath); + script.mScriptPath = VFS::Path::Normalized(scriptPath); script.mFlags = 0; // Parse tags diff --git a/components/lua/configuration.hpp b/components/lua/configuration.hpp index eb2a4cd9a5..4a619019ba 100644 --- a/components/lua/configuration.hpp +++ b/components/lua/configuration.hpp @@ -4,8 +4,9 @@ #include #include -#include "components/esm/luascripts.hpp" -#include "components/esm3/cellref.hpp" +#include +#include +#include namespace LuaUtil { @@ -19,7 +20,8 @@ namespace LuaUtil size_t size() const { return mScripts.size(); } const ESM::LuaScriptCfg& operator[](int id) const { return mScripts[id]; } - std::optional findId(std::string_view path) const; + std::optional findId(VFS::Path::NormalizedView path) const; + bool isCustomScript(int id) const { return mScripts[id].mFlags & ESM::LuaScriptCfg::sCustom; } ScriptIdsWithInitializationData getMenuConf() const { return getConfByFlag(ESM::LuaScriptCfg::sMenu); } @@ -32,7 +34,7 @@ namespace LuaUtil ScriptIdsWithInitializationData getConfByFlag(ESM::LuaScriptCfg::Flags flag) const; std::vector mScripts; - std::map> mPathToIndex; + std::map> mPathToIndex; struct DetailedConf { diff --git a/components/lua/scriptscontainer.cpp b/components/lua/scriptscontainer.cpp index ae62d952fa..4f02e73b7f 100644 --- a/components/lua/scriptscontainer.cpp +++ b/components/lua/scriptscontainer.cpp @@ -73,7 +73,7 @@ namespace LuaUtil if (mScripts.count(scriptId) != 0) return false; // already present - const std::string& path = scriptPath(scriptId); + const VFS::Path::Normalized& path = scriptPath(scriptId); std::string debugName = mNamePrefix; debugName.push_back('['); debugName.append(path); diff --git a/components/lua/scriptscontainer.hpp b/components/lua/scriptscontainer.hpp index 54880b52e1..510052fb64 100644 --- a/components/lua/scriptscontainer.hpp +++ b/components/lua/scriptscontainer.hpp @@ -211,7 +211,7 @@ namespace LuaUtil sol::table mHiddenData; std::map mRegisteredCallbacks; std::map mTemporaryCallbacks; - std::string mPath; + VFS::Path::Normalized mPath; ScriptStats mStats; }; struct Timer @@ -239,7 +239,12 @@ namespace LuaUtil Script& getScript(int scriptId); void printError(int scriptId, std::string_view msg, const std::exception& e); - const std::string& scriptPath(int scriptId) const { return mLua.getConfiguration()[scriptId].mScriptPath; } + + const VFS::Path::Normalized& scriptPath(int scriptId) const + { + return mLua.getConfiguration()[scriptId].mScriptPath; + } + void callOnInit(LuaView& view, int scriptId, const sol::function& onInit, std::string_view data); void callTimer(const Timer& t); void updateTimerQueue(std::vector& timerQueue, double time); diff --git a/components/testing/util.hpp b/components/testing/util.hpp index 65dbfe927d..941f495458 100644 --- a/components/testing/util.hpp +++ b/components/testing/util.hpp @@ -75,7 +75,7 @@ namespace TestingOpenMW } inline std::unique_ptr createTestVFS( - std::initializer_list> files) + std::initializer_list> files) { return createTestVFS(VFS::FileMap(files.begin(), files.end())); }