infrastructure: release resources in test fixture destructors (#9522)

#### Brief overview of PR changes/additions
- Convert the raw owning `LuaInterface*` member in the
`TLuaInterfaceTest` and `TVariableEditorTest` Qt-Test fixtures to
`std::unique_ptr<LuaInterface>` so the fixture's destructor frees it.
- `TLuaInterfaceTest` also stops allocating the interface (and a
`lua_State`) twice: members now init to `nullptr`/empty and are
allocated only in `init()`; `cleanup()` resets the interface before
closing the `lua_State`.

#### Motivation for adding to Mudlet
Keeps the test suite leak-clean and clears static-analysis warnings, per
CLAUDE.md's "smart pointers for non-Qt classes".

#### Other info (issues closed, discussion etc)
- Clears 2 CodeQL `cpp/resource-not-released-in-destructor` warnings
(`test/TVariableEditorTest.cpp`, `test/TLuaInterfaceTest.cpp`).
- Also removes a real runtime leak in `TLuaInterfaceTest`: the old
fixture never deleted the `interface` and double-allocated it
(construction + `init()`), leaking a `LuaInterface` per test plus a
construction-time `lua_State`/`LuaInterface`. Verified gone under
LeakSanitizer (old binary leaked, new binary is leak-clean;
`TVariableEditorTest` already deleted its interface so for it this is
modernization).

**Test case:** Build and run `ctest -R
'TLuaInterfaceTest|TVariableEditorTest'` - both pass (TLuaInterfaceTest
4/4, TVariableEditorTest 96 passed/13 skipped). Optionally run
`./test/TLuaInterfaceTest` with `ASAN_OPTIONS=detect_leaks=1` to confirm
no leaks are reported.
This commit is contained in:
Vadim Peretokin 2026-07-29 13:45:22 +02:00 committed by GitHub
parent 045dfc69e6
commit 1dfd5c4605
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 20 additions and 12 deletions

View file

@ -22,6 +22,8 @@
#include <VarUnit.h>
#include <QtTest/QtTest>
#include <memory>
extern "C" {
#if defined(INCLUDE_VERSIONED_LUA_HEADERS)
#include <lua5.1/lauxlib.h>
@ -35,26 +37,30 @@ extern "C" {
}
class TVarTest : public QObject {
Q_OBJECT
class TVarTest : public QObject
{
Q_OBJECT
private:
lua_State* L = luaL_newstate();
LuaInterface* interface = new LuaInterface(L);
lua_State* L = nullptr;
std::unique_ptr<LuaInterface> interface;
private slots: // NOLINT(readability-redundant-access-specifiers)
void init()
{
L = luaL_newstate();
interface = new LuaInterface(L);
interface = std::make_unique<LuaInterface>(L);
}
void cleanup() {
void cleanup()
{
interface.reset();
lua_close(L);
}
void execLua(const QString& string) {
void execLua(const QString& string)
{
luaL_loadstring(L, string.toUtf8().constData());
lua_pcall(L, 0, 0, 0);
}
@ -84,7 +90,6 @@ private slots: // NOLINT(readability-redundant-access-specifiers)
QCOMPARE(testVar->getValue(), "1");
QCOMPARE(testVar->getValueType(), LUA_TNUMBER);
}
};
#include "TLuaInterfaceTest.moc"