#### 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> |
||
|---|---|---|
| .. | ||
| ci | ||
| functional_tests | ||
| CMakeLists.txt | ||
| CMakeListsConsistencyTest.cpp | ||
| compare-perf-baseline.py | ||
| CredentialManagerKeychainTest.cpp | ||
| CredentialManagerTest.cpp | ||
| DiscordTest.cpp | ||
| EventLoopPumpTest.cpp | ||
| GUIConsoleTests.mpackage | ||
| LuaLiteralTest.cpp | ||
| OAuthClientFlowTest.cpp | ||
| PasswordMigrationTest.cpp | ||
| ProfileNameValidationTest.cpp | ||
| README.md | ||
| ReleaseChecksumPairingTest.cpp | ||
| ReleasePlatformAssetTest.cpp | ||
| SecureStringUtilsTest.cpp | ||
| TAreaGridIndexTest.cpp | ||
| TAreaZLevelIndexTest.cpp | ||
| TEncodingHelperTest.cpp | ||
| TEntityHandlerTest.cpp | ||
| TEntityResolverTest.cpp | ||
| TKeySequenceEditTest.cpp | ||
| TLinkStoreTest.cpp | ||
| TLuaInterfaceTest.cpp | ||
| TMediaPathTraversalTest.cpp | ||
| TMxpCustomElementTagHandlerTest.cpp | ||
| TMxpEdgeCasesTest.cpp | ||
| TMxpElementDefinitionHandlerTest.cpp | ||
| TMxpEntityTagHandlerTest.cpp | ||
| TMxpFormattingTagsTest.cpp | ||
| TMxpFrameDestTagHandlerTest.cpp | ||
| TMxpModeSecurityTest.cpp | ||
| TMxpSendTagHandlerTest.cpp | ||
| TMxpStubClient.h | ||
| TMxpTagParserTest.cpp | ||
| TMxpVersionTagTest.cpp | ||
| TTextEditBlinkTest.cpp | ||
| TVariableEditorTest.cpp | ||
| UntrustedTextTest.cpp | ||
| XdgRecipeConsistencyTest.cpp | ||
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
- Open the Project: Open Mudlet's main CMakeLists.txt in Qt Creator
- Run tests:
Tools→Tests→Run 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
-
Create Test File: Create
YourTestName.cppin thetest/directory. Keep the wordsinstall,uninstall,setup,updateandpatchout 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. -
Implement Test Class: Follow the structure above, inheriting from
QObjectand usingQ_OBJECTmacro -
Add to CMakeLists.txt: Edit
test/CMakeLists.txtand add:add_executable(YourTestName YourTestName.cpp ../src/SourceFileToTest.cpp) add_test(NAME YourTestName COMMAND YourTestName) -
Link Dependencies: Add any required libraries:
target_link_libraries(YourTestName Qt6::Core Qt6::Test) -
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 checksQVERIFY(condition)for boolean conditionsQVERIFY_EXCEPTION_THROWN(expression, exception)for exception testing
- Test Data: For data-driven tests, use
QFETCHandQTest::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(" "), " ");
QCOMPARE(resolver.getResolution(">"), ">");
QCOMPARE(resolver.getResolution("<"), "<");
QCOMPARE(resolver.getResolution("&"), "&");
}
};
QTEST_MAIN(TEntityResolverTest)
#include "TEntityResolverTest.moc"