From 4529af9b7fca26ab41323757ec993f3692ea63d7 Mon Sep 17 00:00:00 2001 From: Evil Eye Date: Fri, 23 Aug 2024 22:40:39 +0200 Subject: [PATCH] Fix the tests --- apps/components_tests/lua/test_async.cpp | 28 ++-- apps/components_tests/lua/test_l10n.cpp | 145 +++++++++-------- apps/components_tests/lua/test_lua.cpp | 45 +++--- .../lua/test_scriptscontainer.cpp | 40 +++-- apps/components_tests/lua/test_storage.cpp | 152 +++++++++--------- apps/components_tests/lua/test_ui_content.cpp | 9 +- apps/openmw/mwlua/mwscriptbindings.cpp | 2 +- 7 files changed, 224 insertions(+), 197 deletions(-) diff --git a/apps/components_tests/lua/test_async.cpp b/apps/components_tests/lua/test_async.cpp index e4010e319f..eb6ce7116a 100644 --- a/apps/components_tests/lua/test_async.cpp +++ b/apps/components_tests/lua/test_async.cpp @@ -13,12 +13,14 @@ namespace { void SetUp() override { - mLua.sol()["callback"] = [&](sol::protected_function fn) -> LuaUtil::Callback { - sol::table hiddenData(mLua.sol(), sol::create); - hiddenData[LuaUtil::ScriptsContainer::sScriptIdKey] = LuaUtil::ScriptId{}; - return LuaUtil::Callback{ std::move(fn), hiddenData }; - }; - mLua.sol()["pass"] = [this](LuaUtil::Callback callback) { mCb = callback; }; + mLua.protectedCall([&](LuaUtil::LuaView& view) { + view.sol()["callback"] = [&](sol::protected_function fn) -> LuaUtil::Callback { + sol::table hiddenData(view.sol(), sol::create); + hiddenData[LuaUtil::ScriptsContainer::sScriptIdKey] = LuaUtil::ScriptId{}; + return LuaUtil::Callback{ std::move(fn), hiddenData }; + }; + view.sol()["pass"] = [&](LuaUtil::Callback callback) { mCb = callback; }; + }); } LuaUtil::LuaState mLua{ nullptr, nullptr }; @@ -28,25 +30,29 @@ namespace TEST_F(LuaCoroutineCallbackTest, CoroutineCallbacks) { internal::CaptureStdout(); - mLua.sol().safe_script(R"X( + mLua.protectedCall([&](LuaUtil::LuaView& view) { + view.sol().safe_script(R"X( local s = 'test' coroutine.wrap(function() pass(callback(function(v) print(s) end)) end)() )X"); - mLua.sol().collect_garbage(); - mCb.call(); + view.sol().collect_garbage(); + mCb.call(); + }); EXPECT_THAT(internal::GetCapturedStdout(), "test\n"); } TEST_F(LuaCoroutineCallbackTest, ErrorInCoroutineCallbacks) { - mLua.sol().safe_script(R"X( + mLua.protectedCall([&](LuaUtil::LuaView& view) { + view.sol().safe_script(R"X( coroutine.wrap(function() pass(callback(function() error('COROUTINE CALLBACK') end)) end)() )X"); - mLua.sol().collect_garbage(); + view.sol().collect_garbage(); + }); EXPECT_ERROR(mCb.call(), "COROUTINE CALLBACK"); } } diff --git a/apps/components_tests/lua/test_l10n.cpp b/apps/components_tests/lua/test_l10n.cpp index a9194ffd7b..d58bd41a94 100644 --- a/apps/components_tests/lua/test_l10n.cpp +++ b/apps/components_tests/lua/test_l10n.cpp @@ -81,84 +81,87 @@ you_have_arrows: "Arrows count: {count}" TEST_F(LuaL10nTest, L10n) { LuaUtil::LuaState lua{ mVFS.get(), &mCfg }; - sol::state_view& l = lua.sol(); - internal::CaptureStdout(); - l10n::Manager l10nManager(mVFS.get()); - l10nManager.setPreferredLocales({ "de", "en" }); - EXPECT_THAT(internal::GetCapturedStdout(), "Preferred locales: gmst de en\n"); + lua.protectedCall([&](LuaUtil::LuaView& view) { + sol::state_view& l = view.sol(); + internal::CaptureStdout(); + l10n::Manager l10nManager(mVFS.get()); + l10nManager.setPreferredLocales({ "de", "en" }); + EXPECT_THAT(internal::GetCapturedStdout(), "Preferred locales: gmst de en\n"); - l["l10n"] = LuaUtil::initL10nLoader(l, &l10nManager); + l["l10n"] = LuaUtil::initL10nLoader(l, &l10nManager); - internal::CaptureStdout(); - l.safe_script("t1 = l10n('Test1')"); - EXPECT_THAT(internal::GetCapturedStdout(), - "Language file \"l10n/Test1/de.yaml\" is enabled\n" - "Language file \"l10n/Test1/en.yaml\" is enabled\n"); + internal::CaptureStdout(); + l.safe_script("t1 = l10n('Test1')"); + EXPECT_THAT(internal::GetCapturedStdout(), + "Language file \"l10n/Test1/de.yaml\" is enabled\n" + "Language file \"l10n/Test1/en.yaml\" is enabled\n"); - internal::CaptureStdout(); - l.safe_script("t2 = l10n('Test2')"); - { - std::string output = internal::GetCapturedStdout(); - EXPECT_THAT(output, HasSubstr("Language file \"l10n/Test2/en.yaml\" is enabled")); - } + internal::CaptureStdout(); + l.safe_script("t2 = l10n('Test2')"); + { + std::string output = internal::GetCapturedStdout(); + EXPECT_THAT(output, HasSubstr("Language file \"l10n/Test2/en.yaml\" is enabled")); + } - EXPECT_EQ(get(l, "t1('good_morning')"), "Guten Morgen."); - EXPECT_EQ(get(l, "t1('you_have_arrows', {count=1})"), "Du hast ein Pfeil."); - EXPECT_EQ(get(l, "t1('you_have_arrows', {count=5})"), "Du hast 5 Pfeile."); - EXPECT_EQ(get(l, "t1('Hello {name}!', {name='World'})"), "Hallo World!"); - EXPECT_EQ(get(l, "t2('good_morning')"), "Morning!"); - EXPECT_EQ(get(l, "t2('you_have_arrows', {count=3})"), "Arrows count: 3"); + EXPECT_EQ(get(l, "t1('good_morning')"), "Guten Morgen."); + EXPECT_EQ(get(l, "t1('you_have_arrows', {count=1})"), "Du hast ein Pfeil."); + EXPECT_EQ(get(l, "t1('you_have_arrows', {count=5})"), "Du hast 5 Pfeile."); + EXPECT_EQ(get(l, "t1('Hello {name}!', {name='World'})"), "Hallo World!"); + EXPECT_EQ(get(l, "t2('good_morning')"), "Morning!"); + EXPECT_EQ(get(l, "t2('you_have_arrows', {count=3})"), "Arrows count: 3"); - internal::CaptureStdout(); - l10nManager.setPreferredLocales({ "en", "de" }); - EXPECT_THAT(internal::GetCapturedStdout(), - "Preferred locales: gmst en de\n" - "Language file \"l10n/Test1/en.yaml\" is enabled\n" - "Language file \"l10n/Test1/de.yaml\" is enabled\n" - "Language file \"l10n/Test2/en.yaml\" is enabled\n"); + internal::CaptureStdout(); + l10nManager.setPreferredLocales({ "en", "de" }); + EXPECT_THAT(internal::GetCapturedStdout(), + "Preferred locales: gmst en de\n" + "Language file \"l10n/Test1/en.yaml\" is enabled\n" + "Language file \"l10n/Test1/de.yaml\" is enabled\n" + "Language file \"l10n/Test2/en.yaml\" is enabled\n"); - EXPECT_EQ(get(l, "t1('good_morning')"), "Good morning."); - EXPECT_EQ(get(l, "t1('you_have_arrows', {count=1})"), "You have one arrow."); - EXPECT_EQ(get(l, "t1('you_have_arrows', {count=5})"), "You have 5 arrows."); - EXPECT_EQ(get(l, "t1('pc_must_come', {PCGender=\"male\"})"), "He is coming with us."); - EXPECT_EQ(get(l, "t1('pc_must_come', {PCGender=\"female\"})"), "She is coming with us."); - EXPECT_EQ(get(l, "t1('pc_must_come', {PCGender=\"blah\"})"), "They are coming with us."); - EXPECT_EQ(get(l, "t1('pc_must_come', {PCGender=\"other\"})"), "They are coming with us."); - EXPECT_EQ(get(l, "t1('quest_completion', {done=0.1})"), "The quest is 10% complete."); - EXPECT_EQ(get(l, "t1('quest_completion', {done=1})"), "The quest is 100% complete."); - EXPECT_EQ(get(l, "t1('ordinal', {num=1})"), "You came in 1st place."); - EXPECT_EQ(get(l, "t1('ordinal', {num=100})"), "You came in 100th place."); - EXPECT_EQ(get(l, "t1('spellout', {num=1})"), "There is one thing."); - EXPECT_EQ(get(l, "t1('spellout', {num=100})"), "There are one hundred things."); - EXPECT_EQ(get(l, "t1('duration', {num=100})"), "It took 1:40"); - EXPECT_EQ(get(l, "t1('numbers', {int=123, double=123.456})"), - "123 and 123 are integers, but 123.456 is a double"); - EXPECT_EQ(get(l, "t1('rounding', {value=123.456789})"), "123.46"); - // Check that failed messages display the key instead of an empty string - EXPECT_EQ(get(l, "t1('{mismatched_braces')"), "{mismatched_braces"); - EXPECT_EQ(get(l, "t1('{unknown_arg}')"), "{unknown_arg}"); - EXPECT_EQ(get(l, "t1('{num, integer}', {num=1})"), "{num, integer}"); - // Doesn't give a valid currency symbol with `en`. Not that openmw is designed for real world currency. - l10nManager.setPreferredLocales({ "en-US", "de" }); - EXPECT_EQ(get(l, "t1('currency', {money=10000.10})"), "You have $10,000.10"); - // Note: Not defined in English localisation file, so we fall back to the German before falling back to the key - EXPECT_EQ(get(l, "t1('Hello {name}!', {name='World'})"), "Hallo World!"); - EXPECT_EQ(get(l, "t2('good_morning')"), "Morning!"); - EXPECT_EQ(get(l, "t2('you_have_arrows', {count=3})"), "Arrows count: 3"); + EXPECT_EQ(get(l, "t1('good_morning')"), "Good morning."); + EXPECT_EQ(get(l, "t1('you_have_arrows', {count=1})"), "You have one arrow."); + EXPECT_EQ(get(l, "t1('you_have_arrows', {count=5})"), "You have 5 arrows."); + EXPECT_EQ(get(l, "t1('pc_must_come', {PCGender=\"male\"})"), "He is coming with us."); + EXPECT_EQ(get(l, "t1('pc_must_come', {PCGender=\"female\"})"), "She is coming with us."); + EXPECT_EQ(get(l, "t1('pc_must_come', {PCGender=\"blah\"})"), "They are coming with us."); + EXPECT_EQ(get(l, "t1('pc_must_come', {PCGender=\"other\"})"), "They are coming with us."); + EXPECT_EQ(get(l, "t1('quest_completion', {done=0.1})"), "The quest is 10% complete."); + EXPECT_EQ(get(l, "t1('quest_completion', {done=1})"), "The quest is 100% complete."); + EXPECT_EQ(get(l, "t1('ordinal', {num=1})"), "You came in 1st place."); + EXPECT_EQ(get(l, "t1('ordinal', {num=100})"), "You came in 100th place."); + EXPECT_EQ(get(l, "t1('spellout', {num=1})"), "There is one thing."); + EXPECT_EQ(get(l, "t1('spellout', {num=100})"), "There are one hundred things."); + EXPECT_EQ(get(l, "t1('duration', {num=100})"), "It took 1:40"); + EXPECT_EQ(get(l, "t1('numbers', {int=123, double=123.456})"), + "123 and 123 are integers, but 123.456 is a double"); + EXPECT_EQ(get(l, "t1('rounding', {value=123.456789})"), "123.46"); + // Check that failed messages display the key instead of an empty string + EXPECT_EQ(get(l, "t1('{mismatched_braces')"), "{mismatched_braces"); + EXPECT_EQ(get(l, "t1('{unknown_arg}')"), "{unknown_arg}"); + EXPECT_EQ(get(l, "t1('{num, integer}', {num=1})"), "{num, integer}"); + // Doesn't give a valid currency symbol with `en`. Not that openmw is designed for real world currency. + l10nManager.setPreferredLocales({ "en-US", "de" }); + EXPECT_EQ(get(l, "t1('currency', {money=10000.10})"), "You have $10,000.10"); + // Note: Not defined in English localisation file, so we fall back to the German before falling back to the + // key + EXPECT_EQ(get(l, "t1('Hello {name}!', {name='World'})"), "Hallo World!"); + EXPECT_EQ(get(l, "t2('good_morning')"), "Morning!"); + EXPECT_EQ(get(l, "t2('you_have_arrows', {count=3})"), "Arrows count: 3"); - // Test that locales with variants and country codes fall back to more generic locales - internal::CaptureStdout(); - l10nManager.setPreferredLocales({ "en-GB-oed", "de" }); - EXPECT_THAT(internal::GetCapturedStdout(), - "Preferred locales: gmst en_GB_OED de\n" - "Language file \"l10n/Test1/en.yaml\" is enabled\n" - "Language file \"l10n/Test1/de.yaml\" is enabled\n" - "Language file \"l10n/Test2/en.yaml\" is enabled\n"); - EXPECT_EQ(get(l, "t2('you_have_arrows', {count=3})"), "Arrows count: 3"); + // Test that locales with variants and country codes fall back to more generic locales + internal::CaptureStdout(); + l10nManager.setPreferredLocales({ "en-GB-oed", "de" }); + EXPECT_THAT(internal::GetCapturedStdout(), + "Preferred locales: gmst en_GB_OED de\n" + "Language file \"l10n/Test1/en.yaml\" is enabled\n" + "Language file \"l10n/Test1/de.yaml\" is enabled\n" + "Language file \"l10n/Test2/en.yaml\" is enabled\n"); + EXPECT_EQ(get(l, "t2('you_have_arrows', {count=3})"), "Arrows count: 3"); - // Test setting fallback language - l.safe_script("t3 = l10n('Test3', 'de')"); - l10nManager.setPreferredLocales({ "en" }); - EXPECT_EQ(get(l, "t3('Hello {name}!', {name='World'})"), "Hallo World!"); + // Test setting fallback language + l.safe_script("t3 = l10n('Test3', 'de')"); + l10nManager.setPreferredLocales({ "en" }); + EXPECT_EQ(get(l, "t3('Hello {name}!', {name='World'})"), "Hallo World!"); + }); } } diff --git a/apps/components_tests/lua/test_lua.cpp b/apps/components_tests/lua/test_lua.cpp index 09f0151267..6596b509db 100644 --- a/apps/components_tests/lua/test_lua.cpp +++ b/apps/components_tests/lua/test_lua.cpp @@ -97,26 +97,26 @@ return { TEST_F(LuaStateTest, ToString) { - EXPECT_EQ(LuaUtil::toString(sol::make_object(mLua.sol(), 3.14)), "3.14"); - EXPECT_EQ(LuaUtil::toString(sol::make_object(mLua.sol(), true)), "true"); + EXPECT_EQ(LuaUtil::toString(sol::make_object(mLua.unsafeState(), 3.14)), "3.14"); + EXPECT_EQ(LuaUtil::toString(sol::make_object(mLua.unsafeState(), true)), "true"); EXPECT_EQ(LuaUtil::toString(sol::nil), "nil"); - EXPECT_EQ(LuaUtil::toString(sol::make_object(mLua.sol(), "something")), "\"something\""); + EXPECT_EQ(LuaUtil::toString(sol::make_object(mLua.unsafeState(), "something")), "\"something\""); } TEST_F(LuaStateTest, Cast) { - EXPECT_EQ(LuaUtil::cast(sol::make_object(mLua.sol(), 3.14)), 3); - EXPECT_ERROR( - LuaUtil::cast(sol::make_object(mLua.sol(), "3.14")), "Value \"\"3.14\"\" can not be casted to int"); - EXPECT_ERROR(LuaUtil::cast(sol::make_object(mLua.sol(), sol::nil)), + EXPECT_EQ(LuaUtil::cast(sol::make_object(mLua.unsafeState(), 3.14)), 3); + EXPECT_ERROR(LuaUtil::cast(sol::make_object(mLua.unsafeState(), "3.14")), + "Value \"\"3.14\"\" can not be casted to int"); + EXPECT_ERROR(LuaUtil::cast(sol::make_object(mLua.unsafeState(), sol::nil)), "Value \"nil\" can not be casted to string"); - EXPECT_ERROR(LuaUtil::cast(sol::make_object(mLua.sol(), sol::nil)), + EXPECT_ERROR(LuaUtil::cast(sol::make_object(mLua.unsafeState(), sol::nil)), "Value \"nil\" can not be casted to string"); - EXPECT_ERROR(LuaUtil::cast(sol::make_object(mLua.sol(), sol::nil)), + EXPECT_ERROR(LuaUtil::cast(sol::make_object(mLua.unsafeState(), sol::nil)), "Value \"nil\" can not be casted to sol::table"); - EXPECT_ERROR(LuaUtil::cast(sol::make_object(mLua.sol(), "3.14")), + EXPECT_ERROR(LuaUtil::cast(sol::make_object(mLua.unsafeState(), "3.14")), "Value \"\"3.14\"\" can not be casted to sol::function"); - EXPECT_ERROR(LuaUtil::cast(sol::make_object(mLua.sol(), "3.14")), + EXPECT_ERROR(LuaUtil::cast(sol::make_object(mLua.unsafeState(), "3.14")), "Value \"\"3.14\"\" can not be casted to sol::function"); } @@ -186,21 +186,22 @@ return { TEST_F(LuaStateTest, ProvideAPI) { LuaUtil::LuaState lua(mVFS.get(), &mCfg); + lua.protectedCall([&](LuaUtil::LuaView& view) { + sol::table api1 = LuaUtil::makeReadOnly(view.sol().create_table_with("name", "api1")); + sol::table api2 = LuaUtil::makeReadOnly(view.sol().create_table_with("name", "api2")); - sol::table api1 = LuaUtil::makeReadOnly(lua.sol().create_table_with("name", "api1")); - sol::table api2 = LuaUtil::makeReadOnly(lua.sol().create_table_with("name", "api2")); + sol::table script1 = lua.runInNewSandbox("bbb/tests.lua", "", { { "test.api", api1 } }); - sol::table script1 = lua.runInNewSandbox("bbb/tests.lua", "", { { "test.api", api1 } }); + lua.addCommonPackage("sqrlib", view.sol().create_table_with("sqr", [](int x) { return x * x; })); - lua.addCommonPackage("sqrlib", lua.sol().create_table_with("sqr", [](int x) { return x * x; })); + sol::table script2 = lua.runInNewSandbox("bbb/tests.lua", "", { { "test.api", api2 } }); - sol::table script2 = lua.runInNewSandbox("bbb/tests.lua", "", { { "test.api", api2 } }); + EXPECT_ERROR(LuaUtil::call(script1["sqr"], 3), "module not found: sqrlib"); + EXPECT_EQ(LuaUtil::call(script2["sqr"], 3).get(), 9); - EXPECT_ERROR(LuaUtil::call(script1["sqr"], 3), "module not found: sqrlib"); - EXPECT_EQ(LuaUtil::call(script2["sqr"], 3).get(), 9); - - EXPECT_EQ(LuaUtil::call(script1["apiName"]).get(), "api1"); - EXPECT_EQ(LuaUtil::call(script2["apiName"]).get(), "api2"); + EXPECT_EQ(LuaUtil::call(script1["apiName"]).get(), "api1"); + EXPECT_EQ(LuaUtil::call(script2["apiName"]).get(), "api2"); + }); } TEST_F(LuaStateTest, GetLuaVersion) @@ -212,7 +213,7 @@ return { { auto getMem = [&] { for (int i = 0; i < 5; ++i) - lua_gc(mLua.sol(), LUA_GCCOLLECT, 0); + lua_gc(mLua.unsafeState(), LUA_GCCOLLECT, 0); return mLua.getTotalMemoryUsage(); }; int64_t memWithScript; diff --git a/apps/components_tests/lua/test_scriptscontainer.cpp b/apps/components_tests/lua/test_scriptscontainer.cpp index c048e29f5e..7491675a01 100644 --- a/apps/components_tests/lua/test_scriptscontainer.cpp +++ b/apps/components_tests/lua/test_scriptscontainer.cpp @@ -198,8 +198,9 @@ CUSTOM, PLAYER: useInterface.lua EXPECT_TRUE(scripts.addCustomScript(*mCfg.findId("stopEvent.lua"))); EXPECT_TRUE(scripts.addCustomScript(*mCfg.findId("test2.lua"))); - std::string X0 = LuaUtil::serialize(mLua.sol().create_table_with("x", 0.5)); - std::string X1 = LuaUtil::serialize(mLua.sol().create_table_with("x", 1.5)); + sol::state_view sol = mLua.unsafeState(); + std::string X0 = LuaUtil::serialize(sol.create_table_with("x", 0.5)); + std::string X1 = LuaUtil::serialize(sol.create_table_with("x", 1.5)); { testing::internal::CaptureStdout(); @@ -243,7 +244,8 @@ CUSTOM, PLAYER: useInterface.lua EXPECT_TRUE(scripts.addCustomScript(*mCfg.findId("test1.lua"))); EXPECT_TRUE(scripts.addCustomScript(*mCfg.findId("stopEvent.lua"))); EXPECT_TRUE(scripts.addCustomScript(*mCfg.findId("test2.lua"))); - std::string X = LuaUtil::serialize(mLua.sol().create_table_with("x", 0.5)); + sol::state_view sol = mLua.unsafeState(); + std::string X = LuaUtil::serialize(sol.create_table_with("x", 0.5)); { testing::internal::CaptureStdout(); @@ -334,8 +336,9 @@ CUSTOM, PLAYER: useInterface.lua scripts1.addAutoStartedScripts(); EXPECT_TRUE(scripts1.addCustomScript(*mCfg.findId("test1.lua"))); - scripts1.receiveEvent("Set", LuaUtil::serialize(mLua.sol().create_table_with("n", 1, "x", 0.5, "y", 3.5))); - scripts1.receiveEvent("Set", LuaUtil::serialize(mLua.sol().create_table_with("n", 2, "x", 2.5, "y", 1.5))); + sol::state_view sol = mLua.unsafeState(); + scripts1.receiveEvent("Set", LuaUtil::serialize(sol.create_table_with("n", 1, "x", 0.5, "y", 3.5))); + scripts1.receiveEvent("Set", LuaUtil::serialize(sol.create_table_with("n", 2, "x", 2.5, "y", 1.5))); ESM::LuaScripts data; scripts1.save(data); @@ -379,10 +382,10 @@ CUSTOM, PLAYER: useInterface.lua EXPECT_EQ(internal::GetCapturedStdout(), ""); int counter1 = 0, counter2 = 0, counter3 = 0, counter4 = 0; - sol::function fn1 = sol::make_object(mLua.sol(), [&]() { counter1++; }); - sol::function fn2 = sol::make_object(mLua.sol(), [&]() { counter2++; }); - sol::function fn3 = sol::make_object(mLua.sol(), [&](int d) { counter3 += d; }); - sol::function fn4 = sol::make_object(mLua.sol(), [&](int d) { counter4 += d; }); + sol::function fn1 = sol::make_object(mLua.unsafeState(), [&]() { counter1++; }); + sol::function fn2 = sol::make_object(mLua.unsafeState(), [&]() { counter2++; }); + sol::function fn3 = sol::make_object(mLua.unsafeState(), [&](int d) { counter3 += d; }); + sol::function fn4 = sol::make_object(mLua.unsafeState(), [&](int d) { counter4 += d; }); scripts.registerTimerCallback(test1Id, "A", fn3); scripts.registerTimerCallback(test1Id, "B", fn4); @@ -391,12 +394,16 @@ CUSTOM, PLAYER: useInterface.lua scripts.processTimers(1, 2); - scripts.setupSerializableTimer(TimerType::SIMULATION_TIME, 10, test1Id, "B", sol::make_object(mLua.sol(), 3)); - scripts.setupSerializableTimer(TimerType::GAME_TIME, 10, test2Id, "B", sol::make_object(mLua.sol(), 4)); - scripts.setupSerializableTimer(TimerType::SIMULATION_TIME, 5, test1Id, "A", sol::make_object(mLua.sol(), 1)); - scripts.setupSerializableTimer(TimerType::GAME_TIME, 5, test2Id, "A", sol::make_object(mLua.sol(), 2)); - scripts.setupSerializableTimer(TimerType::SIMULATION_TIME, 15, test1Id, "A", sol::make_object(mLua.sol(), 10)); - scripts.setupSerializableTimer(TimerType::SIMULATION_TIME, 15, test1Id, "B", sol::make_object(mLua.sol(), 20)); + scripts.setupSerializableTimer( + TimerType::SIMULATION_TIME, 10, test1Id, "B", sol::make_object(mLua.unsafeState(), 3)); + scripts.setupSerializableTimer(TimerType::GAME_TIME, 10, test2Id, "B", sol::make_object(mLua.unsafeState(), 4)); + scripts.setupSerializableTimer( + TimerType::SIMULATION_TIME, 5, test1Id, "A", sol::make_object(mLua.unsafeState(), 1)); + scripts.setupSerializableTimer(TimerType::GAME_TIME, 5, test2Id, "A", sol::make_object(mLua.unsafeState(), 2)); + scripts.setupSerializableTimer( + TimerType::SIMULATION_TIME, 15, test1Id, "A", sol::make_object(mLua.unsafeState(), 10)); + scripts.setupSerializableTimer( + TimerType::SIMULATION_TIME, 15, test1Id, "B", sol::make_object(mLua.unsafeState(), 20)); scripts.setupUnsavableTimer(TimerType::SIMULATION_TIME, 10, test2Id, fn2); scripts.setupUnsavableTimer(TimerType::GAME_TIME, 10, test1Id, fn2); @@ -446,7 +453,8 @@ CUSTOM, PLAYER: useInterface.lua TEST_F(LuaScriptsContainerTest, CallbackWrapper) { - LuaUtil::Callback callback{ mLua.sol()["print"], mLua.newTable() }; + sol::state_view view = mLua.unsafeState(); + LuaUtil::Callback callback{ view["print"], sol::table(view, sol::create) }; callback.mHiddenData[LuaUtil::ScriptsContainer::sScriptDebugNameKey] = "some_script.lua"; callback.mHiddenData[LuaUtil::ScriptsContainer::sScriptIdKey] = LuaUtil::ScriptId{ nullptr, 0 }; diff --git a/apps/components_tests/lua/test_storage.cpp b/apps/components_tests/lua/test_storage.cpp index 165737d1ed..cf6db0ca64 100644 --- a/apps/components_tests/lua/test_storage.cpp +++ b/apps/components_tests/lua/test_storage.cpp @@ -19,102 +19,110 @@ namespace { // Note: LuaUtil::Callback can be used only if Lua is initialized via LuaUtil::LuaState LuaUtil::LuaState luaState{ nullptr, nullptr }; - sol::state_view& mLua = luaState.sol(); - LuaUtil::LuaStorage::initLuaBindings(mLua); - LuaUtil::LuaStorage storage(mLua); - storage.setActive(true); + luaState.protectedCall([](LuaUtil::LuaView& view) { + sol::state_view& lua = view.sol(); + LuaUtil::LuaStorage::initLuaBindings(view); + LuaUtil::LuaStorage storage; + storage.setActive(true); - sol::table callbackHiddenData(mLua, sol::create); - callbackHiddenData[LuaUtil::ScriptsContainer::sScriptIdKey] = LuaUtil::ScriptId{}; - LuaUtil::getAsyncPackageInitializer( - mLua.lua_state(), []() { return 0.0; }, []() { return 0.0; })(callbackHiddenData); - mLua["async"] = LuaUtil::AsyncPackageId{ nullptr, 0, callbackHiddenData }; + sol::table callbackHiddenData(lua, sol::create); + callbackHiddenData[LuaUtil::ScriptsContainer::sScriptIdKey] = LuaUtil::ScriptId{}; + LuaUtil::getAsyncPackageInitializer( + lua.lua_state(), []() { return 0.0; }, []() { return 0.0; })(callbackHiddenData); + lua["async"] = LuaUtil::AsyncPackageId{ nullptr, 0, callbackHiddenData }; - mLua["mutable"] = storage.getMutableSection("test"); - mLua["ro"] = storage.getReadOnlySection("test"); + lua["mutable"] = storage.getMutableSection(lua, "test"); + lua["ro"] = storage.getReadOnlySection(lua, "test"); - mLua.safe_script(R"( - callbackCalls = {} - ro:subscribe(async:callback(function(section, key) - table.insert(callbackCalls, section .. '_' .. (key or '*')) - end)) - )"); + lua.safe_script(R"( + callbackCalls = {} + ro:subscribe(async:callback(function(section, key) + table.insert(callbackCalls, section .. '_' .. (key or '*')) + end)) + )"); - mLua.safe_script("mutable:set('x', 5)"); - EXPECT_EQ(get(mLua, "mutable:get('x')"), 5); - EXPECT_EQ(get(mLua, "ro:get('x')"), 5); + lua.safe_script("mutable:set('x', 5)"); + EXPECT_EQ(get(lua, "mutable:get('x')"), 5); + EXPECT_EQ(get(lua, "ro:get('x')"), 5); - EXPECT_THROW(mLua.safe_script("ro:set('y', 3)"), std::exception); + EXPECT_THROW(lua.safe_script("ro:set('y', 3)"), std::exception); - mLua.safe_script("t1 = mutable:asTable()"); - mLua.safe_script("t2 = ro:asTable()"); - EXPECT_EQ(get(mLua, "t1.x"), 5); - EXPECT_EQ(get(mLua, "t2.x"), 5); + lua.safe_script("t1 = mutable:asTable()"); + lua.safe_script("t2 = ro:asTable()"); + EXPECT_EQ(get(lua, "t1.x"), 5); + EXPECT_EQ(get(lua, "t2.x"), 5); - mLua.safe_script("mutable:reset()"); - EXPECT_TRUE(get(mLua, "ro:get('x') == nil")); + lua.safe_script("mutable:reset()"); + EXPECT_TRUE(get(lua, "ro:get('x') == nil")); - mLua.safe_script("mutable:reset({x=4, y=7})"); - EXPECT_EQ(get(mLua, "ro:get('x')"), 4); - EXPECT_EQ(get(mLua, "ro:get('y')"), 7); + lua.safe_script("mutable:reset({x=4, y=7})"); + EXPECT_EQ(get(lua, "ro:get('x')"), 4); + EXPECT_EQ(get(lua, "ro:get('y')"), 7); - EXPECT_THAT(get(mLua, "table.concat(callbackCalls, ', ')"), "test_x, test_*, test_*"); + EXPECT_THAT(get(lua, "table.concat(callbackCalls, ', ')"), "test_x, test_*, test_*"); + }); } TEST(LuaUtilStorageTest, Table) { - sol::state mLua; - LuaUtil::LuaStorage::initLuaBindings(mLua); - LuaUtil::LuaStorage storage(mLua); - storage.setActive(true); - mLua["mutable"] = storage.getMutableSection("test"); - mLua["ro"] = storage.getReadOnlySection("test"); + LuaUtil::LuaState luaState{ nullptr, nullptr }; + luaState.protectedCall([](LuaUtil::LuaView& view) { + LuaUtil::LuaStorage::initLuaBindings(view); + LuaUtil::LuaStorage storage; + auto& lua = view.sol(); + storage.setActive(true); + lua["mutable"] = storage.getMutableSection(lua, "test"); + lua["ro"] = storage.getReadOnlySection(lua, "test"); - mLua.safe_script("mutable:set('x', { y = 'abc', z = 7 })"); - EXPECT_EQ(get(mLua, "mutable:get('x').z"), 7); - EXPECT_THROW(mLua.safe_script("mutable:get('x').z = 3"), std::exception); - EXPECT_NO_THROW(mLua.safe_script("mutable:getCopy('x').z = 3")); - EXPECT_EQ(get(mLua, "mutable:get('x').z"), 7); - EXPECT_EQ(get(mLua, "ro:get('x').z"), 7); - EXPECT_EQ(get(mLua, "ro:get('x').y"), "abc"); + lua.safe_script("mutable:set('x', { y = 'abc', z = 7 })"); + EXPECT_EQ(get(lua, "mutable:get('x').z"), 7); + EXPECT_THROW(lua.safe_script("mutable:get('x').z = 3"), std::exception); + EXPECT_NO_THROW(lua.safe_script("mutable:getCopy('x').z = 3")); + EXPECT_EQ(get(lua, "mutable:get('x').z"), 7); + EXPECT_EQ(get(lua, "ro:get('x').z"), 7); + EXPECT_EQ(get(lua, "ro:get('x').y"), "abc"); + }); } TEST(LuaUtilStorageTest, Saving) { - sol::state mLua; - LuaUtil::LuaStorage::initLuaBindings(mLua); - LuaUtil::LuaStorage storage(mLua); - storage.setActive(true); + LuaUtil::LuaState luaState{ nullptr, nullptr }; + luaState.protectedCall([](LuaUtil::LuaView& view) { + LuaUtil::LuaStorage::initLuaBindings(view); + LuaUtil::LuaStorage storage; + auto& lua = view.sol(); + storage.setActive(true); - mLua["permanent"] = storage.getMutableSection("permanent"); - mLua["temporary"] = storage.getMutableSection("temporary"); - mLua.safe_script("temporary:removeOnExit()"); - mLua.safe_script("permanent:set('x', 1)"); - mLua.safe_script("temporary:set('y', 2)"); + lua["permanent"] = storage.getMutableSection(lua, "permanent"); + lua["temporary"] = storage.getMutableSection(lua, "temporary"); + lua.safe_script("temporary:removeOnExit()"); + lua.safe_script("permanent:set('x', 1)"); + lua.safe_script("temporary:set('y', 2)"); - const auto tmpFile = std::filesystem::temp_directory_path() / "test_storage.bin"; - storage.save(tmpFile); - EXPECT_EQ(get(mLua, "permanent:get('x')"), 1); - EXPECT_EQ(get(mLua, "temporary:get('y')"), 2); + const auto tmpFile = std::filesystem::temp_directory_path() / "test_storage.bin"; + storage.save(lua, tmpFile); + EXPECT_EQ(get(lua, "permanent:get('x')"), 1); + EXPECT_EQ(get(lua, "temporary:get('y')"), 2); - storage.clearTemporaryAndRemoveCallbacks(); - mLua["permanent"] = storage.getMutableSection("permanent"); - mLua["temporary"] = storage.getMutableSection("temporary"); - EXPECT_EQ(get(mLua, "permanent:get('x')"), 1); - EXPECT_TRUE(get(mLua, "temporary:get('y') == nil")); + storage.clearTemporaryAndRemoveCallbacks(); + lua["permanent"] = storage.getMutableSection(lua, "permanent"); + lua["temporary"] = storage.getMutableSection(lua, "temporary"); + EXPECT_EQ(get(lua, "permanent:get('x')"), 1); + EXPECT_TRUE(get(lua, "temporary:get('y') == nil")); - mLua.safe_script("permanent:set('x', 3)"); - mLua.safe_script("permanent:set('z', 4)"); + lua.safe_script("permanent:set('x', 3)"); + lua.safe_script("permanent:set('z', 4)"); - LuaUtil::LuaStorage storage2(mLua); - storage2.setActive(true); - storage2.load(tmpFile); - mLua["permanent"] = storage2.getMutableSection("permanent"); - mLua["temporary"] = storage2.getMutableSection("temporary"); + LuaUtil::LuaStorage storage2; + storage2.setActive(true); + storage2.load(lua, tmpFile); + lua["permanent"] = storage2.getMutableSection(lua, "permanent"); + lua["temporary"] = storage2.getMutableSection(lua, "temporary"); - EXPECT_EQ(get(mLua, "permanent:get('x')"), 1); - EXPECT_TRUE(get(mLua, "permanent:get('z') == nil")); - EXPECT_TRUE(get(mLua, "temporary:get('y') == nil")); + EXPECT_EQ(get(lua, "permanent:get('x')"), 1); + EXPECT_TRUE(get(lua, "permanent:get('z') == nil")); + EXPECT_TRUE(get(lua, "temporary:get('y') == nil")); + }); } } diff --git a/apps/components_tests/lua/test_ui_content.cpp b/apps/components_tests/lua/test_ui_content.cpp index c4f23634ce..fcdfd8a1b3 100644 --- a/apps/components_tests/lua/test_ui_content.cpp +++ b/apps/components_tests/lua/test_ui_content.cpp @@ -27,7 +27,7 @@ namespace return LuaUi::ContentView(result.get()); } - sol::table makeTable() { return sol::table(mLuaState.sol(), sol::create); } + sol::table makeTable() { return sol::table(mLuaState.unsafeState(), sol::create); } sol::table makeTable(std::string name) { @@ -39,13 +39,14 @@ namespace TEST_F(LuaUiContentTest, ProtectedMetatable) { - mLuaState.sol()["makeContent"] = mNew; - mLuaState.sol()["M"] = makeContent(makeTable()).getMetatable(); + sol::state_view sol = mLuaState.unsafeState(); + sol["makeContent"] = mNew; + sol["M"] = makeContent(makeTable()).getMetatable(); std::string testScript = R"( assert(not pcall(function() setmetatable(makeContent{}, {}) end), 'Metatable is not protected') assert(getmetatable(makeContent{}) == false, 'Metatable is not protected') )"; - EXPECT_NO_THROW(mLuaState.sol().safe_script(testScript)); + EXPECT_NO_THROW(sol.safe_script(testScript)); } TEST_F(LuaUiContentTest, Create) diff --git a/apps/openmw/mwlua/mwscriptbindings.cpp b/apps/openmw/mwlua/mwscriptbindings.cpp index 2a92a6c5af..90d24b39fe 100644 --- a/apps/openmw/mwlua/mwscriptbindings.cpp +++ b/apps/openmw/mwlua/mwscriptbindings.cpp @@ -95,7 +95,7 @@ namespace MWLua sol::table initMWScriptBindings(const Context& context) { - sol::state_view lua = lua; + sol::state_view lua = context.sol(); sol::table api(lua, sol::create); api["getGlobalScript"]