Skip to content

Commit

Permalink
Fix the tests
Browse files Browse the repository at this point in the history
  • Loading branch information
Assumeru committed Aug 23, 2024
1 parent c978334 commit 4529af9
Show file tree
Hide file tree
Showing 7 changed files with 248 additions and 221 deletions.
28 changes: 17 additions & 11 deletions apps/components_tests/lua/test_async.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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 };
Expand All @@ -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");
}
}
161 changes: 82 additions & 79 deletions apps/components_tests/lua/test_l10n.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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");

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("t2 = l10n('Test2')");
{
std::string output = internal::GetCapturedStdout();
EXPECT_THAT(output, HasSubstr("Language file \"l10n/Test2/en.yaml\" is enabled"));
}

EXPECT_EQ(get<std::string>(l, "t1('good_morning')"), "Guten Morgen.");
EXPECT_EQ(get<std::string>(l, "t1('you_have_arrows', {count=1})"), "Du hast ein Pfeil.");
EXPECT_EQ(get<std::string>(l, "t1('you_have_arrows', {count=5})"), "Du hast 5 Pfeile.");
EXPECT_EQ(get<std::string>(l, "t1('Hello {name}!', {name='World'})"), "Hallo World!");
EXPECT_EQ(get<std::string>(l, "t2('good_morning')"), "Morning!");
EXPECT_EQ(get<std::string>(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");

EXPECT_EQ(get<std::string>(l, "t1('good_morning')"), "Good morning.");
EXPECT_EQ(get<std::string>(l, "t1('you_have_arrows', {count=1})"), "You have one arrow.");
EXPECT_EQ(get<std::string>(l, "t1('you_have_arrows', {count=5})"), "You have 5 arrows.");
EXPECT_EQ(get<std::string>(l, "t1('pc_must_come', {PCGender=\"male\"})"), "He is coming with us.");
EXPECT_EQ(get<std::string>(l, "t1('pc_must_come', {PCGender=\"female\"})"), "She is coming with us.");
EXPECT_EQ(get<std::string>(l, "t1('pc_must_come', {PCGender=\"blah\"})"), "They are coming with us.");
EXPECT_EQ(get<std::string>(l, "t1('pc_must_come', {PCGender=\"other\"})"), "They are coming with us.");
EXPECT_EQ(get<std::string>(l, "t1('quest_completion', {done=0.1})"), "The quest is 10% complete.");
EXPECT_EQ(get<std::string>(l, "t1('quest_completion', {done=1})"), "The quest is 100% complete.");
EXPECT_EQ(get<std::string>(l, "t1('ordinal', {num=1})"), "You came in 1st place.");
EXPECT_EQ(get<std::string>(l, "t1('ordinal', {num=100})"), "You came in 100th place.");
EXPECT_EQ(get<std::string>(l, "t1('spellout', {num=1})"), "There is one thing.");
EXPECT_EQ(get<std::string>(l, "t1('spellout', {num=100})"), "There are one hundred things.");
EXPECT_EQ(get<std::string>(l, "t1('duration', {num=100})"), "It took 1:40");
EXPECT_EQ(get<std::string>(l, "t1('numbers', {int=123, double=123.456})"),
"123 and 123 are integers, but 123.456 is a double");
EXPECT_EQ(get<std::string>(l, "t1('rounding', {value=123.456789})"), "123.46");
// Check that failed messages display the key instead of an empty string
EXPECT_EQ(get<std::string>(l, "t1('{mismatched_braces')"), "{mismatched_braces");
EXPECT_EQ(get<std::string>(l, "t1('{unknown_arg}')"), "{unknown_arg}");
EXPECT_EQ(get<std::string>(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<std::string>(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<std::string>(l, "t1('Hello {name}!', {name='World'})"), "Hallo World!");
EXPECT_EQ(get<std::string>(l, "t2('good_morning')"), "Morning!");
EXPECT_EQ(get<std::string>(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<std::string>(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<std::string>(l, "t3('Hello {name}!', {name='World'})"), "Hallo World!");
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);

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

EXPECT_EQ(get<std::string>(l, "t1('good_morning')"), "Guten Morgen.");
EXPECT_EQ(get<std::string>(l, "t1('you_have_arrows', {count=1})"), "Du hast ein Pfeil.");
EXPECT_EQ(get<std::string>(l, "t1('you_have_arrows', {count=5})"), "Du hast 5 Pfeile.");
EXPECT_EQ(get<std::string>(l, "t1('Hello {name}!', {name='World'})"), "Hallo World!");
EXPECT_EQ(get<std::string>(l, "t2('good_morning')"), "Morning!");
EXPECT_EQ(get<std::string>(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");

EXPECT_EQ(get<std::string>(l, "t1('good_morning')"), "Good morning.");
EXPECT_EQ(get<std::string>(l, "t1('you_have_arrows', {count=1})"), "You have one arrow.");
EXPECT_EQ(get<std::string>(l, "t1('you_have_arrows', {count=5})"), "You have 5 arrows.");
EXPECT_EQ(get<std::string>(l, "t1('pc_must_come', {PCGender=\"male\"})"), "He is coming with us.");
EXPECT_EQ(get<std::string>(l, "t1('pc_must_come', {PCGender=\"female\"})"), "She is coming with us.");
EXPECT_EQ(get<std::string>(l, "t1('pc_must_come', {PCGender=\"blah\"})"), "They are coming with us.");
EXPECT_EQ(get<std::string>(l, "t1('pc_must_come', {PCGender=\"other\"})"), "They are coming with us.");
EXPECT_EQ(get<std::string>(l, "t1('quest_completion', {done=0.1})"), "The quest is 10% complete.");
EXPECT_EQ(get<std::string>(l, "t1('quest_completion', {done=1})"), "The quest is 100% complete.");
EXPECT_EQ(get<std::string>(l, "t1('ordinal', {num=1})"), "You came in 1st place.");
EXPECT_EQ(get<std::string>(l, "t1('ordinal', {num=100})"), "You came in 100th place.");
EXPECT_EQ(get<std::string>(l, "t1('spellout', {num=1})"), "There is one thing.");
EXPECT_EQ(get<std::string>(l, "t1('spellout', {num=100})"), "There are one hundred things.");
EXPECT_EQ(get<std::string>(l, "t1('duration', {num=100})"), "It took 1:40");
EXPECT_EQ(get<std::string>(l, "t1('numbers', {int=123, double=123.456})"),
"123 and 123 are integers, but 123.456 is a double");
EXPECT_EQ(get<std::string>(l, "t1('rounding', {value=123.456789})"), "123.46");
// Check that failed messages display the key instead of an empty string
EXPECT_EQ(get<std::string>(l, "t1('{mismatched_braces')"), "{mismatched_braces");
EXPECT_EQ(get<std::string>(l, "t1('{unknown_arg}')"), "{unknown_arg}");
EXPECT_EQ(get<std::string>(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<std::string>(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<std::string>(l, "t1('Hello {name}!', {name='World'})"), "Hallo World!");
EXPECT_EQ(get<std::string>(l, "t2('good_morning')"), "Morning!");
EXPECT_EQ(get<std::string>(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<std::string>(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<std::string>(l, "t3('Hello {name}!', {name='World'})"), "Hallo World!");
});
}
}
45 changes: 23 additions & 22 deletions apps/components_tests/lua/test_lua.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<int>(sol::make_object(mLua.sol(), 3.14)), 3);
EXPECT_ERROR(
LuaUtil::cast<int>(sol::make_object(mLua.sol(), "3.14")), "Value \"\"3.14\"\" can not be casted to int");
EXPECT_ERROR(LuaUtil::cast<std::string_view>(sol::make_object(mLua.sol(), sol::nil)),
EXPECT_EQ(LuaUtil::cast<int>(sol::make_object(mLua.unsafeState(), 3.14)), 3);
EXPECT_ERROR(LuaUtil::cast<int>(sol::make_object(mLua.unsafeState(), "3.14")),
"Value \"\"3.14\"\" can not be casted to int");
EXPECT_ERROR(LuaUtil::cast<std::string_view>(sol::make_object(mLua.unsafeState(), sol::nil)),
"Value \"nil\" can not be casted to string");
EXPECT_ERROR(LuaUtil::cast<std::string>(sol::make_object(mLua.sol(), sol::nil)),
EXPECT_ERROR(LuaUtil::cast<std::string>(sol::make_object(mLua.unsafeState(), sol::nil)),
"Value \"nil\" can not be casted to string");
EXPECT_ERROR(LuaUtil::cast<sol::table>(sol::make_object(mLua.sol(), sol::nil)),
EXPECT_ERROR(LuaUtil::cast<sol::table>(sol::make_object(mLua.unsafeState(), sol::nil)),
"Value \"nil\" can not be casted to sol::table");
EXPECT_ERROR(LuaUtil::cast<sol::function>(sol::make_object(mLua.sol(), "3.14")),
EXPECT_ERROR(LuaUtil::cast<sol::function>(sol::make_object(mLua.unsafeState(), "3.14")),
"Value \"\"3.14\"\" can not be casted to sol::function");
EXPECT_ERROR(LuaUtil::cast<sol::protected_function>(sol::make_object(mLua.sol(), "3.14")),
EXPECT_ERROR(LuaUtil::cast<sol::protected_function>(sol::make_object(mLua.unsafeState(), "3.14")),
"Value \"\"3.14\"\" can not be casted to sol::function");
}

Expand Down Expand Up @@ -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", lua.sol().create_table_with("sqr", [](int x) { return x * x; }));
lua.addCommonPackage("sqrlib", view.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<int>(), 9);
EXPECT_ERROR(LuaUtil::call(script1["sqr"], 3), "module not found: sqrlib");
EXPECT_EQ(LuaUtil::call(script2["sqr"], 3).get<int>(), 9);

EXPECT_EQ(LuaUtil::call(script1["apiName"]).get<std::string>(), "api1");
EXPECT_EQ(LuaUtil::call(script2["apiName"]).get<std::string>(), "api2");
EXPECT_EQ(LuaUtil::call(script1["apiName"]).get<std::string>(), "api1");
EXPECT_EQ(LuaUtil::call(script2["apiName"]).get<std::string>(), "api2");
});
}

TEST_F(LuaStateTest, GetLuaVersion)
Expand All @@ -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;
Expand Down
Loading

0 comments on commit 4529af9

Please sign in to comment.