diff --git a/apps/openmw_test_suite/lua/test_lua.cpp b/apps/openmw_test_suite/lua/test_lua.cpp index ebfb76eee1..76d430b440 100644 --- a/apps/openmw_test_suite/lua/test_lua.cpp +++ b/apps/openmw_test_suite/lua/test_lua.cpp @@ -51,10 +51,26 @@ return { } )X"); + std::string genBigScript() + { + std::stringstream buf; + buf << "return function()\n"; + buf << " x = {}\n"; + for (int i = 0; i < 1000; ++i) + buf << " x[" << i * 2 << "] = " << i << "\n"; + buf << " return x\n"; + buf << "end\n"; + return buf.str(); + } + + TestingOpenMW::VFSTestFile bigScriptFile(genBigScript()); + 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 } }); + { "bbb/tests.lua", &testsFile }, { "invalid.lua", &invalidScriptFile }, { "big.lua", &bigScriptFile }, + { "requireBig.lua", &requireBigScriptFile } }); LuaUtil::ScriptsConfiguration mCfg; LuaUtil::LuaState mLua{ mVFS.get(), &mCfg }; @@ -172,4 +188,22 @@ return { EXPECT_THAT(LuaUtil::getLuaVersion(), HasSubstr("Lua")); } + TEST_F(LuaStateTest, RemovedScriptsGarbageCollecting) + { + auto getMem = [&] { + for (int i = 0; i < 5; ++i) + lua_gc(mLua.sol(), LUA_GCCOLLECT, 0); + return mLua.getTotalMemoryUsage(); + }; + int64_t memWithScript; + { + sol::object s = mLua.runInNewSandbox("requireBig.lua"); + memWithScript = getMem(); + } + for (int i = 0; i < 100; ++i) // run many times to make small memory leaks visible + mLua.runInNewSandbox("requireBig.lua"); + int64_t memWithoutScript = getMem(); + // At this moment all instances of the script should be garbage-collected. + EXPECT_LT(memWithoutScript, memWithScript); + } }