mudlet/test
Vadim Peretokin f8eb6b5597
fix: saved variables holding functions come back empty again instead of half-filled (#9860)
#### Brief overview of PR changes/additions

- A saved variable with a function, userdata or coroutine anywhere
inside it now exports only the members registered in `savedVars`, which
for a table ticked while empty is an empty group. Tables holding nothing
but data keep the full save added in #9762.
- The save-time walk records which saved globals hold such a value;
`XMLexport` turns the ride-along off for those variables only. Silent,
and it costs nothing outside a save.
- New `SavedVariableFenceTest` pins all 11 measured shapes, on disk and
after a reload.

#### Motivation for adding to Mudlet

A half-restored table defeats the `if next(t) == nil then rebuild() end`
guard packages carry, which kills cron-daemon's scheduler permanently on
its first minute wake after a restart.

#### Other info (issues closed, discussion etc)

Fixes #9857

**Test case:** install cron-daemon, tick `cron` in the Variables view,
add a job with a `command` function, restart and wait for the minute
rollover - the daemon keeps running (measured 2/2 canary fires, against
0/2 before).

Assisted-by: Claude:claude-opus-5
Signed-off-by: Vadim Peretokin <vadim.peretokin@mudlet.org>
2026-08-13 15:49:17 +02:00
..
ci infrastructure: reject a release tag that does not match APP_VERSION (#9701) 2026-08-07 06:14:11 +02:00
functional_tests fix: saved variables holding functions come back empty again instead of half-filled (#9860) 2026-08-13 15:49:17 +02:00
CMakeLists.txt infrastructure: fix a test running against the real config dir, and guard the recipe (#9811) 2026-08-11 10:56:38 +02:00
CMakeListsConsistencyTest.cpp Infrastructure: Make sure every source file is included in the build list (#9350) 2026-06-20 10:48:17 +00:00
compare-perf-baseline.py fix: new profiles process game text about twice as fast (#9705) 2026-08-08 09:04:14 +00:00
CredentialManagerKeychainTest.cpp fix: keep saved profile passwords working on Windows after qtkeychain library update (#9395) 2026-07-12 20:59:37 +02:00
CredentialManagerTest.cpp fix: keep saved profile passwords working on Windows after qtkeychain library update (#9395) 2026-07-12 20:59:37 +02:00
DiscordTest.cpp infrastructure: drop comments that restate the code beside them (#9681) 2026-08-11 08:06:16 +02:00
EventLoopPumpTest.cpp fix: stop the test-only waitForEvent() wedging Mudlet on macOS (#9691) 2026-08-07 06:12:30 +02:00
GUIConsoleTests.mpackage
LuaLiteralTest.cpp improve: OSC 8 hyperlink handling, and a setting to turn it off (#9731) 2026-08-08 10:09:32 +02:00
OAuthClientFlowTest.cpp improve: OSC 8 hyperlink handling, and a setting to turn it off (#9731) 2026-08-08 10:09:32 +02:00
PasswordMigrationTest.cpp
ProfileNameValidationTest.cpp fix: a profile named "." or ".." deletes every profile when removed (#9722) 2026-08-08 08:30:14 +02:00
README.md infrastructure: rename the six tests Windows refuses to launch without elevation (#9753) 2026-08-11 08:07:10 +02:00
ReleaseChecksumPairingTest.cpp infrastructure: rename the six tests Windows refuses to launch without elevation (#9753) 2026-08-11 08:07:10 +02:00
ReleasePlatformAssetTest.cpp infrastructure: rename the six tests Windows refuses to launch without elevation (#9753) 2026-08-11 08:07:10 +02:00
SecureStringUtilsTest.cpp infrastructure: drop comments that restate the code beside them (#9681) 2026-08-11 08:06:16 +02:00
TAreaGridIndexTest.cpp improve: 2D mapper rendering speed on single-Z-level areas (#9209) 2026-04-23 06:18:21 +02:00
TAreaZLevelIndexTest.cpp improve: 2D mapper rendering speed on single-Z-level areas (#9209) 2026-04-23 06:18:21 +02:00
TEncodingHelperTest.cpp Fix: Restore Chinese and Korean text that showed up garbled (#9349) 2026-06-20 12:32:47 +02:00
TEntityHandlerTest.cpp
TEntityResolverTest.cpp fix: stop a malicious game from writing files outside the media folder (#9504) 2026-07-25 17:23:31 +02:00
TKeySequenceEditTest.cpp infrastructure: fix milestone assignment, unbreak the key sequence tests (#9679) 2026-08-06 06:07:10 +02:00
TLinkStoreTest.cpp fix: clickable links could show the wrong colours and styling after heavy output (#9406) 2026-07-12 20:45:24 +02:00
TLuaInterfaceTest.cpp infrastructure: release resources in test fixture destructors (#9522) 2026-07-29 13:45:22 +02:00
TMediaPathTraversalTest.cpp fix: stop a malicious game from writing files outside the media folder (#9504) 2026-07-25 17:23:31 +02:00
TMxpCustomElementTagHandlerTest.cpp
TMxpEdgeCasesTest.cpp Fix: resolve CodeQL stack-address-escape warnings (#9080) 2026-04-08 20:34:02 +02:00
TMxpElementDefinitionHandlerTest.cpp Fix: Text with < characters disappearing on games with MXP enabled (#8918) 2026-03-21 17:45:49 +00:00
TMxpEntityTagHandlerTest.cpp fix: MXP text now shows correctly on non-English games (#9491) 2026-07-27 19:55:26 +02:00
TMxpFormattingTagsTest.cpp
TMxpFrameDestTagHandlerTest.cpp
TMxpModeSecurityTest.cpp Fix: Text with < characters disappearing on games with MXP enabled (#8918) 2026-03-21 17:45:49 +00:00
TMxpSendTagHandlerTest.cpp fix: MXP text now shows correctly on non-English games (#9491) 2026-07-27 19:55:26 +02:00
TMxpStubClient.h fix: MXP text now shows correctly on non-English games (#9491) 2026-07-27 19:55:26 +02:00
TMxpTagParserTest.cpp
TMxpVersionTagTest.cpp
TTextEditBlinkTest.cpp Fix: Keep blinking text updating reliably (#9321) 2026-06-15 09:49:08 +02:00
TVariableEditorTest.cpp infrastructure: release resources in test fixture destructors (#9522) 2026-07-29 13:45:22 +02:00
UntrustedTextTest.cpp improve: OSC 8 hyperlink handling, and a setting to turn it off (#9731) 2026-08-08 10:09:32 +02:00
XdgRecipeConsistencyTest.cpp infrastructure: fix a test running against the real config dir, and guard the recipe (#9811) 2026-08-11 10:56:38 +02:00

Mudlet C++ Qt Tests

This directory contains unit tests for Mudlet's C++ codebase using the Qt Test framework.

Running Tests

Command Line

From the build directory, you can run tests using several methods:

Run all tests

# go into the build directory, wherever that might be
cd build/

# run test
ctest --verbose

Run specific tests

# Run a single test by name
ctest -R TEntityResolverTest

# Run tests matching a pattern
ctest -R "TMxp.*"

Qt Creator integration

Qt Creator provides excellent integration for running and debugging Qt tests:

Running tests from Qt Creator

  1. Open the Project: Open Mudlet's main CMakeLists.txt in Qt Creator
  2. Run tests: ToolsTestsRun All Tests

Contributing New Tests

Test Structure

All Qt tests in Mudlet follow this basic structure:

#include <QtTest/QtTest>
#include <SourceFileToTest.h>

class MyComponentTest : public QObject {
    Q_OBJECT

private slots:
    void initTestCase() {
        // Setup before all tests
    }

    void init() {
        // Setup before each test
    }

    void testBasicFunctionality() {
        // Your test implementation
        QCOMPARE(actualValue, expectedValue);
        QVERIFY(condition);
    }

    void cleanup() {
        // Cleanup after each test
    }

    void cleanupTestCase() {
        // Cleanup after all tests
    }
};

QTEST_MAIN(MyComponentTest)
#include "MyComponentTest.moc"

Adding a New Test

  1. Create Test File: Create YourTestName.cpp in the test/ directory. Keep the words install, uninstall, setup, update and patch out of the name: Windows takes an unsigned executable named that way for an installer and will not start it from an ordinary, non-elevated Windows shell. CMake rejects such a name at configure time.

  2. Implement Test Class: Follow the structure above, inheriting from QObject and using Q_OBJECT macro

  3. Add to CMakeLists.txt: Edit test/CMakeLists.txt and add:

    add_executable(YourTestName YourTestName.cpp ../src/SourceFileToTest.cpp)
    add_test(NAME YourTestName COMMAND YourTestName)
    
  4. Link Dependencies: Add any required libraries:

    target_link_libraries(YourTestName Qt6::Core Qt6::Test)
    
  5. Include Source Files: Include the source files you're testing (see existing examples)

Best Practices

  • Test Naming: Use descriptive test method names like testEntityResolutionWithStandardEntities()
  • Test Independence: Each test should be independent and not rely on other tests
  • Setup/Cleanup: Use init()/cleanup() for per-test setup, initTestCase()/cleanupTestCase() for global setup
  • Assertions: Use appropriate Qt Test macros:
    • QCOMPARE(actual, expected) for equality checks
    • QVERIFY(condition) for boolean conditions
    • QVERIFY_EXCEPTION_THROWN(expression, exception) for exception testing
  • Test Data: For data-driven tests, use QFETCH and QTest::addColumn

Example: Simple Test Implementation

#include <QtTest/QtTest>
#include <TEntityResolver.h>

class TEntityResolverTest : public QObject {
    Q_OBJECT

private slots:
    void testStandardEntities() {
        TEntityResolver resolver;

        QCOMPARE(resolver.getResolution("&nbsp;"), " ");
        QCOMPARE(resolver.getResolution("&gt;"), ">");
        QCOMPARE(resolver.getResolution("&lt;"), "<");
        QCOMPARE(resolver.getResolution("&amp;"), "&");
    }
};

QTEST_MAIN(TEntityResolverTest)
#include "TEntityResolverTest.moc"